threads-mcp
An MCP server for Meta's Threads that acts as your own account, enabling reading profiles, posts, replies, timeline, search, and performing actions like posting, replying, liking, following, and scheduling, using a real logged-in browser session.
README
threads-mcp
An MCP server for Meta's Threads that acts as your own account — read profiles, posts, replies, your timeline & search, and post / reply / quote / like / repost / follow / schedule — from any MCP client (Claude Desktop, Claude Code, etc.).
No developer account. Unlike the official Threads Graph API approach (which needs an app, OAuth, and an Instagram Business account), this server drives a real logged-in browser session using your own cookies.
Contents: Rate limits · Tools · Media · Scheduling · Setup · Run as a daemon · Config · How it works · Troubleshooting
Full reference: Documentation · Changelog: CHANGELOG.md · Versioning & releases: docs/RELEASES.md
⚠️ Behave for rate limits
You are automating a real Threads account. Meta rate-limits aggressively and can restrict or ban accounts that behave like bots — bursty posting, rapid follow/unfollow, like loops. This server helps, but the discipline is on you:
- Writes are spaced ≥
THREADS_MIN_ACTION_INTERVAL_MS(default 8s) apart, enforced server-side. - Treat
create_thread,follow_user,like_threadas scarce actions, not loops. - If you hit a
🐢 rate-limitedmessage, stop for several minutes — don't retry immediately. - Reads are cheaper but still hit a real session; results are cached briefly.
Tools
21 tools. Posts are identified by a full url or handle + code (the shortcode in .../@user/post/CODE).
Read
| Tool | What it returns |
|---|---|
whoami |
Which account you're signed in as (handle, user id, name, follower/following). |
get_profile |
A user's bio, follower count, verified status + recent posts. Omit handle for your own. |
get_user_threads |
A user's recent posts (their profile feed). |
get_thread |
A single post with its like/reply/repost counts. |
get_thread_replies |
Replies under a post. |
get_timeline |
Your "For you" home feed. |
search |
Search Threads for posts or users. |
get_followers |
A partial sample of a user's followers. |
Write (rate-limited — real account)
| Tool | Action |
|---|---|
create_thread |
Post a new thread — text and/or media. |
reply_to_thread |
Reply to a post — text and/or media. |
quote_thread |
Quote-post (repost with your own comment + optional media). |
delete_thread |
Delete one of your own posts (permanent). |
like_thread / unlike_thread |
Like / remove a like. |
repost_thread / unrepost_thread |
Repost / remove a repost. |
follow_user / unfollow_user |
Follow / unfollow a user. |
Schedule
| Tool | Action |
|---|---|
schedule_thread |
Queue a text/media post to publish later (at ISO time or in duration). |
list_scheduled |
List scheduled posts and their status. |
cancel_scheduled |
Cancel a pending scheduled post by id. |
Note: reposting your own post is a no-op on Threads (it silently does nothing) — that's Threads' behavior, not a bug.
Tool annotations
Per the MCP annotations spec — side effects at a glance. Write tools act on your real account.
| Tool | Read-only | Idempotent | Destructive |
|---|---|---|---|
whoami, get_profile, get_user_threads, get_thread, get_thread_replies, get_timeline, search, get_followers |
✓ | ✓ | – |
create_thread, reply_to_thread, quote_thread |
– | – | – |
like_thread / unlike_thread, repost_thread / unrepost_thread, follow_user / unfollow_user |
– | ✓ | – |
delete_thread |
– | ✓ | ✓ |
schedule_thread |
– | – | – |
list_scheduled |
✓ | ✓ | – |
cancel_scheduled |
– | ✓ | – |
Media
create_thread, reply_to_thread, quote_thread, and schedule_thread take an optional media array — local file paths and/or http(s) URLs (URLs are downloaded to a temp file first, then cleaned up). Supported: images (jpg/png/webp/avif) and video (mp4/mov/webm). Multiple images post as a carousel. Either text or media is required.
// text + single image
create_thread { "text": "hello", "media": ["/path/to/pic.jpg"] }
// carousel (multiple images, mix local + URL)
create_thread { "text": "trip 🧵", "media": ["a.jpg", "b.jpg", "https://…/c.jpg"] }
// image-only reply
reply_to_thread { "handle": "someone", "code": "ABC123", "media": ["reaction.png"] }
// quote with a comment + image
quote_thread { "url": "https://www.threads.com/@x/post/ABC", "text": "this 👇", "media": ["chart.png"] }
Scheduling
Threads' web UI has no native scheduling (it's a mobile / Meta Business Suite feature), so this server runs its own scheduler: jobs are persisted to ~/.threads-mcp/scheduled.json and a poll loop publishes them when due, through the same code path as create_thread.
// absolute time (local timezone unless you add an offset like +07:00 or Z)
schedule_thread { "text": "launch 🚀", "at": "2026-07-20T09:00" }
// relative delay
schedule_thread { "text": "in a bit", "in": "2h", "media": ["teaser.jpg"] }
list_scheduled {} // → ids + status (pending / done / failed / canceled)
cancel_scheduled { "id": "b9ec…" }
The one hard limit
A cookie/browser approach can only post while this server process is running — there's no Threads-side scheduler to hand the job to. So:
- Short horizons / same session — works while your MCP client keeps the server alive.
- Past-due jobs — fire on the next startup (better late than never).
- Long horizons (days out) — run the server as an always-on daemon so it's alive when the job is due.
Local media paths must still exist when the job fires (URLs are re-downloaded at fire time).
From npm (recommended)
npm install -g @bintangtimurlangit/threads-mcp # downloads the CloakBrowser binary (~200 MB, cached)
This puts two commands on your PATH: threads-mcp (the server) and threads-mcp-login (one-time login). Or run without installing: npx -y @bintangtimurlangit/threads-mcp.
From source
git clone https://github.com/bintangtimurlangit/threads-mcp.git
cd threads-mcp
npm install # also downloads the CloakBrowser binary (~200 MB, cached)
npm run build
1. Log in once
threads-mcp-login # global install — or, from a source checkout: npm run login
Opens a CloakBrowser window — log into Threads, then press Enter. Saves your session to ~/.threads-mcp/chrome-profile. Re-run only when it expires.
2. Register with your MCP client
The server launches a headed browser, so it needs a display. On a headless machine wrap it with xvfb-run:
{
"mcpServers": {
"threads": {
"command": "xvfb-run",
"args": ["-a", "threads-mcp"]
}
}
}
On a machine with a real display, drop xvfb-run: "command": "threads-mcp", "args": []. From a source checkout, use "command": "node", "args": ["/absolute/path/to/threads-mcp/build/index.js"] (wrapped in xvfb-run on a headless box).
Running as a persistent daemon
For reliable scheduling (and to avoid re-launching the browser each session), run the server always-on under a virtual display. Example with systemd on Linux:
# ~/.config/systemd/user/threads-mcp.service
[Unit]
Description=threads-mcp (Threads MCP server)
After=network-online.target
[Service]
ExecStart=/usr/bin/xvfb-run -a /usr/bin/node /absolute/path/to/threads-mcp/build/index.js
Restart=on-failure
Environment=DEBUG=false
[Install]
WantedBy=default.target
systemctl --user enable --now threads-mcp
loginctl enable-linger "$USER" # keep it running after logout
Or with pm2: pm2 start "xvfb-run -a node build/index.js" --name threads-mcp.
Note: MCP over stdio expects the client to own the process. Running a standalone daemon is specifically for the scheduler to survive between client sessions — the scheduled-post queue is shared via
~/.threads-mcp/scheduled.json.
Configuration
All optional — see .env.example, copy to .env to override.
| Variable | Default | Purpose |
|---|---|---|
THREADS_DOMAIN |
threads.com |
Threads domain (threads.net redirects here). |
THREADS_PROFILE_DIR |
~/.threads-mcp/chrome-profile |
Where the saved login lives. |
THREADS_HEADLESS |
false |
Keep false — headless is detected. |
THREADS_MIN_ACTION_INTERVAL_MS |
8000 |
Minimum gap between write actions. Raise to be safer. |
CACHE_TTL_MS |
30000 |
In-memory read-cache lifetime. |
DEBUG |
false |
Log startup, captured GraphQL op names, and scheduler activity to stderr. |
State lives under ~/.threads-mcp/: chrome-profile/ (your login) and scheduled.json (the post queue).
How it works
Threads' web app talks to Meta's Relay GraphQL gateway with per-session tokens (fb_dtsg, lsd) and anti-automation fingerprinting. A hand-rolled fetch gets rejected, and operation IDs churn. So this server drives CloakBrowser — a fingerprint-patched Chromium — against a persistent profile you log into once, and:
- Reads — collects the data the app renders: the server-side JSON embedded in each page's
<script>tags, plus every/api/graphqland/graphql/queryresponse (the home feed uses the latter). A defensive walker pulls posts/users out of whatever comes back, so it survives Meta renaming operations. - Writes — drive the real composer and action buttons so Meta's own client mints the tokens. Icon buttons are clicked at the DOM level (a humanized pointer click misses them). Replies use the inline composer's Ctrl+Enter; reply-with-media promotes it to the full dialog via "Expand composer".
- Scheduling — a persisted queue + poll loop, delegating to the same publish path as
create_thread.
The browser runs headed (Meta detects headless); on a server use a virtual display (xvfb).
Development
npm run typecheck
npm test # live READ-only smoke test (needs login + a display)
npm run dev # tsx watch
DEBUG=true logs every GraphQL operation name the app fires and each scheduler tick — useful if Meta reshuffles a surface and a reader comes back empty.
Troubleshooting
| Symptom | Likely cause / fix |
|---|---|
🔒 Not signed in on every tool |
No/expired session → run npm run login. |
| A read returns empty for a public account | Try again (feed/timeline is lazy-loaded); run with DEBUG=true to see the GraphQL ops. Private/blocked accounts yield nothing. |
| A write says it couldn't find its button | Meta changed the UI, or a promo interstitial got in the way (the server tries to dismiss those). Retry; if persistent, the selector needs updating. |
🐢 rate-limited |
Stop for several minutes, then slow down. |
| Scheduled post never fired | The server wasn't running when it was due — see Run as a daemon. It'll fire on next startup. |
| Headless / server has no display | Wrap the command in xvfb-run -a …. |
Caveats
- Login required. No session → tools return a friendly "run
npm run login" prompt. - Anti-bot is a moving target. The free CloakBrowser binary can go stale as Meta updates detection; CloakBrowser Pro ships newer patches. Writes rely on UI selectors Meta can change.
- Reads are resilient to GraphQL renames (they parse whatever the app fetches), but a private/blocked account yields nothing, and just-posted content can be briefly stale on read-back.
- Scheduling only fires while the server runs (see above).
- Respect Threads' Terms of Service and the rate-limit guidance above. This is for personal use of your own account, not scraping or automation at scale.
Contributing & security
CONTRIBUTING.md · SECURITY.md · Code of Conduct
License
Disclaimer
This is an unofficial project. It is not affiliated with, authorized, maintained, sponsored, or endorsed by Meta, Threads, or Instagram.
It works by driving a real logged-in browser session against Threads' web app, which can change without notice — a tool may break when Meta updates its site or anti-bot behavior. It automates your own account and performs only the actions you invoke.
You are responsible for using this software in compliance with Threads' / Meta's Terms of Service and applicable law. Keep request and write volumes reasonable. All product names, logos, and brands are property of their respective owners.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。