Skip to main content
Glama
Andre-wyap

Threads MCP Server

by Andre-wyap

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)

  • mcp package, 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)

Related MCP server: MCP Calendar Assistant

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):

  1. 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.

  2. 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.

  3. 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)

  4. 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 .env in place). Public profiles can extend grants by refreshing; private profiles must re-authorize after expiry.

  5. 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 due

  • published — always skipped

  • skipped — always skipped

  • publishing — safety marker while a chain is being sent

  • error — 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 × impressions per 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 error and 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

  • .env is git-ignored; keep it that way. Set file permissions to 600 on shared machines.

  • Before exposing the dashboard beyond localhost, set DASHBOARD_USERNAME and DASHBOARD_PASSWORD in .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.

F
license - not found
-
quality - not tested
-
maintenance - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Andre-wyap/threads-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server