Threads MCP Server
Enables AI assistants to manage a Threads posting schedule through natural language, allowing them to view, add, update, reschedule, and skip posts in a local CSV schedule.
README
Safe Threads Auto-Poster & Planner
A local, safety-first scheduler for Threads posts using Meta's official Threads API.
- Autoposter (
threads_autoposter.py) — publishes due posts from a CSV schedule. Locked in dry-run mode until you explicitly approve live posting. - Planner dashboard (
threads_dashboard.py) — a local web UI with calendar and list views for adding, editing, skipping, and tracking single posts and multi-part thread chains. No Terminal or CSV editing needed day to day. - MCP server (
threads_mcp_server.py) — lets AI assistants such as Claude (Claude Desktop / Claude Code) or Codex manage your schedule with natural language.
Everything runs from one folder and one CSV file (threads_schedule.csv), so the dashboard, the autoposter, and the AI assistant always see the same schedule.
Requirements
- Python 3.10 or newer (the autoposter and dashboard use only the standard library)
mcppackage, only if you want the Claude/Codex integration:pip install -r requirements.txt- A Meta Developer account and a Meta app with the Threads use case (see step 2)
Step-by-step setup
1. Get the code
git clone https://github.com/<your-username>/<your-repo>.git
cd <your-repo>
cp .env.example .env
.env holds your private settings and tokens. It is listed in .gitignore and must never be committed. Never paste tokens or app secrets into an AI chat either — put them only in your local .env.
2. Create a Meta app and get Threads API credentials
Meta's current flow (verified July 2026):
- In the Meta Developer dashboard, create an app with the Threads use case. Meta issues separate Threads app credentials; use the Threads app ID and its matching secret.
- Add your Threads account as a Threads Tester in the app dashboard, then accept the invitation in your Threads account settings (Website permissions → Invitations). Accounts without an app/tester role need approved permissions through App Review and a published app.
- Authorize the account with the official OAuth flow using these permissions:
threads_basic(required for everything)threads_content_publish(publishing)threads_manage_replies(needed for multi-part thread chains)
- Exchange the short-lived token (1 hour) for a long-lived token (60 days). Refresh it before expiry by running
python3 refresh_threads_token.py(it calls Meta's official refresh endpoint and updates.envin place). Public profiles can extend grants by refreshing; private profiles must re-authorize after expiry. - Note your Threads user ID — you'll need it together with the token.
Official references: Threads API · Get Started · Create Posts · Create Replies · Rate Limits
3. Fill in .env
Open .env and set at minimum:
THREADS_ACCESS_TOKEN=your-long-lived-token
THREADS_USER_ID=your-threads-user-id
Leave the safety locks as they are (DRY_RUN=true, APPROVED_TO_POST=false). See .env.example for every field and what it does.
4. Set your schedule start date and dry-run
python3 threads_autoposter.py --set-start-date YYYY-MM-DD
python3 threads_autoposter.py
The first command fills in dates for every calendar item. The second is a dry run — it selects the next due post and logs exactly what it would publish, without any API call.
Inspect what would happen at a specific moment:
python3 threads_autoposter.py --now 2026-08-01T09:01:00+08:00
Run the test suite any time:
python3 -m unittest -v test_threads_autoposter.py
5. Open the planner dashboard
python3 threads_dashboard.py
(On macOS you can instead double-click Open Threads Planner.command.) The dashboard opens at http://127.0.0.1:8765 (change with --host/--port). Keep the Terminal window open while using it; press Control+C to stop.
The planner supports calendar and upcoming-list views, single posts and multi-part chains, topics and filtering, scheduled/skipped/error/published statuses, UTF-8 byte checks for every post part, and safe deletion of unpublished entries. Published rows are read-only, and the dashboard never edits .env or enables live posting.
6. Approve live posting (deliberately)
Live posting requires all three settings in .env:
DRY_RUN=false
APPROVED_TO_POST=true
LIVE_POSTING_CONFIRMATION=I approve live Threads posting.
Test one specific row first:
TEST_MODE=true
TEST_POST_ID=D01-AM
Test mode selects only that row but does not bypass any safety lock. After a successful test, set TEST_MODE=false.
Pause posting at any time by setting DRY_RUN=true or APPROVED_TO_POST=false.
7. Run it on a schedule
Run the autoposter every 15 minutes from the project folder:
cd /absolute/path/to/this/folder && python3 threads_autoposter.py
Each run processes at most one due item, uses a local lock so overlapping runs exit safely, and respects all safety settings.
You can host the scheduler on your own computer (macOS launchd or Linux cron) or on an always-on VPS with systemd — full walkthroughs for both, including the systemd unit files, private dashboard access over SSH, and monthly token refresh, are in DEPLOYMENT.md.
Keep the automation disabled or dry-run-only until the schedule has a start date and you have reviewed the dry-run output. Run the scheduler in exactly one place — post statuses live in the local CSV and do not sync between machines.
Using it with Claude or Codex (MCP)
threads_mcp_server.py exposes the planner over the Model Context Protocol via stdio. It edits the same CSV as the dashboard and never exposes .env secrets. Tools available to the assistant:
safety_status, list_posts, get_post, add_post, update_post, reschedule_post, skip_post, mark_published, run_scheduler_once (obeys all DRY_RUN/approval locks).
Install the dependency first: pip install "mcp[cli]>=1.27,<2".
Claude Desktop
Add to claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"threads-planner": {
"command": "python3",
"args": ["/absolute/path/to/this/folder/threads_mcp_server.py"]
}
}
}
If the planner lives on a remote server, run it over SSH instead — see claude_desktop_mcp_config.example.json for both variants.
Claude Code
claude mcp add threads-planner -- python3 /absolute/path/to/this/folder/threads_mcp_server.py
Codex CLI
Add to ~/.codex/config.toml:
[mcp_servers.threads-planner]
command = "python3"
args = ["/absolute/path/to/this/folder/threads_mcp_server.py"]
Then ask things like: "List next week's scheduled threads", "Add a 3-part chain about client onboarding on Friday at 9am", or "Skip post D14-PM".
The schedule CSV
threads_schedule.csv is the single source of truth. You can also edit it in a spreadsheet (UTF-8, keep the exact column names, close the editor before the scheduler runs). Valid statuses:
scheduled— eligible when duepublished— always skippedskipped— always skippedpublishing— safety marker while a chain is being senterror— skipped until you inspect the error and deliberately reset it
post_text holds a JSON list of strings — one entry per post in the chain. Logs are written to logs/threads_autoposter.log; every selection, dry run, container, publish, retry, and error is recorded. Tokens are never logged.
Threads API limits (as of July 2026)
- Text: 500 UTF-8 bytes per post segment (emoji count by bytes)
- API-published posts: 250 per profile per rolling 24 hours; replies: 1,000
- General call quota:
4,800 × impressionsper rolling 24 hours (minimum 10 impressions in the formula) - Check your usage with
GET /{threads-user-id}/threads_publishing_limit
There is no native future-time scheduling in the Threads publishing flow — this local scheduler decides when to call the API. A typical two-chains-per-day calendar (2 roots + 8 replies) sits comfortably below the limits.
Troubleshooting
- Blank dates — run
--set-start-date YYYY-MM-DD. - 401 / invalid token — renew the OAuth token (or refresh the long-lived token) and update only your local
.env. - Permission error — confirm the tester invitation was accepted (or App Review passed) and all three permissions were granted.
- Container timeout — the row is marked
errorand partial published IDs are retained to prevent duplicates; inspect the logged Meta error. - 429 / rate limit — leave the row in
error, wait for the rolling window, check quota usage, then reset deliberately. - Partial chain — don't reset blindly. Check
threads_post_id(a JSON list of already-published IDs) and finish manually or edit the remaining content before rescheduling. - CSV locked or damaged — restore the exact header listed above using a UTF-8 CSV editor.
Security notes
.envis git-ignored; keep it that way. Set file permissions to600on shared machines.- Before exposing the dashboard beyond localhost, set
DASHBOARD_USERNAMEandDASHBOARD_PASSWORDin.env(never reuse your Meta password). - Meta describes publishing as acting on a person's behalf. External users (no app role) require App Review and a published app — check Meta's current Platform Terms before running this for accounts other than your own.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.