threads-mcp
A Model Context Protocol (MCP) server for the Threads API. Exposes 26 tools covering profile management, content reading, publishing, replies, and discovery.
Quick Start
1. Get a Threads Access Token
You can start using Threads API immediately for your own account via the Threads Tester — no App Review required for self-use.
- Go to developers.facebook.com/tools/explorer
- Select your Threads App from the app dropdown (or create one at developers.facebook.com/apps with the Threads product)
- In the Threads Tester, generate a short-lived token
- To get a long-lived token (60 days), call:
curl "https://graph.threads.net/access_token?grant_type=th_exchange_token&client_id=YOUR_APP_ID&client_secret=YOUR_APP_SECRET&access_token=SHORT_LIVED_TOKEN"
- To refresh a long-lived token before it expires:
curl "https://graph.threads.net/refresh_access_token?grant_type=th_refresh_token&access_token=LONG_LIVED_TOKEN"
Note: Long-lived tokens expire after 60 days. Refresh them at least once per 60 days. There is no refresh token — you must always refresh before expiry.
2. Set Environment Variables
export THREADS_ACCESS_TOKEN=your_access_token_here
# Optional: skip the GET /me call at startup by providing your user ID directly
export THREADS_USER_ID=your_threads_user_id
3. Run the Server
# Install globally
npm install -g threads-mcp
# Or run directly
npx threads-mcp
Or build from source:
git clone https://github.com/your-repo/threads-mcp
cd threads-mcp
pnpm install
pnpm build
THREADS_ACCESS_TOKEN=your_token node dist/index.js
Claude Desktop Configuration
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"threads": {
"command": "npx",
"args": ["-y", "threads-mcp"],
"env": {
"THREADS_ACCESS_TOKEN": "your_access_token_here"
}
}
}
}
Or if installed globally:
{
"mcpServers": {
"threads": {
"command": "threads-mcp",
"env": {
"THREADS_ACCESS_TOKEN": "your_access_token_here",
"THREADS_USER_ID": "your_user_id_optional"
}
}
}
}
Cursor Configuration
Add to .cursor/mcp.json in your project root, or ~/.cursor/mcp.json globally:
{
"mcpServers": {
"threads": {
"command": "npx",
"args": ["-y", "threads-mcp"],
"env": {
"THREADS_ACCESS_TOKEN": "your_access_token_here"
}
}
}
}
Tools Reference
Profile Tools
| Tool | Description | Required Permission |
|---|---|---|
get_profile |
Get your Threads profile (username, bio, follower count) | threads_basic |
get_publishing_limit |
Check remaining publishing quota (250 posts/24h) | threads_content_publish |
get_account_insights |
Account-level analytics (views, likes, followers) | threads_read_replies or threads_manage_insights |
Content Tools
| Tool | Description | Required Permission |
|---|---|---|
list_my_threads |
Paginated list of your posts | threads_basic |
list_my_replies |
Paginated list of your replies | threads_basic |
get_thread |
Get details of a specific post | threads_basic |
get_thread_insights |
Engagement metrics for a post | threads_manage_insights |
get_mentions |
Posts where you've been @mentioned | threads_basic |
Publishing Tools
| Tool | Description | Required Permission |
|---|---|---|
create_text_post |
Create/publish a text post | threads_content_publish |
create_image_post |
Create/publish a post with an image | threads_content_publish |
create_video_post |
Create a video post container | threads_content_publish |
create_carousel_post |
Create a multi-media carousel post | threads_content_publish |
publish_thread |
Publish a container created with publish:false |
threads_content_publish |
get_container_status |
Check if a video container finished processing | threads_content_publish |
delete_thread |
Delete one of your posts | threads_content_publish |
repost_thread |
Repost another user's thread | threads_content_publish |
quote_thread |
Quote-post another thread with your commentary | threads_content_publish |
Replies Tools
| Tool | Description | Required Permission |
|---|---|---|
get_replies |
Get direct replies to a post | threads_read_replies |
get_conversation |
Get full conversation thread | threads_read_replies |
reply_to_thread |
Post a reply to a thread | threads_content_publish |
manage_reply |
Hide or unhide a reply on your posts | threads_manage_replies |
Discovery Tools
| Tool | Description | Required Permission |
|---|---|---|
search_keyword |
Search posts by keyword | threads_keyword_search ⚠️ |
lookup_profile |
Look up a user profile by username | threads_profile_discovery ⚠️ |
list_profile_posts |
List posts from any public user | threads_basic |
search_locations |
Search for location tags | threads_basic |
get_location |
Get details about a location | threads_basic |
⚠️ App Review required for
threads_keyword_searchandthreads_profile_discovery. These permissions require Meta's App Review process before they can be used in production. For self-use development, you may be able to use them in Development mode with your own account only.
Publishing Workflow
Text Post (simplest)
Tool: create_text_post
text: "Hello, Threads!"
publish: true ← publishes immediately
Video Post (requires polling)
1. Tool: create_video_post
video_url: "https://..."
publish: false ← don't auto-publish; get container ID
2. Tool: get_container_status
container_id: "from step 1"
→ poll until status = FINISHED
3. Tool: publish_thread
container_id: "from step 1"
Carousel Post
1. Tool: create_carousel_post
items: [{type: IMAGE, url: "..."}, {type: IMAGE, url: "..."}]
publish: true ← auto-publish carousel
Rate Limits
- Publishing: 250 posts per 24 hours (use
get_publishing_limitto check) - API rate limits: Follow standard Meta API rate limits (~200 calls/hour per user for most endpoints)
- Video processing: Videos typically take 10–30 seconds; poll with
get_container_status
Security
- The
THREADS_ACCESS_TOKENis never logged or included in tool responses - All outgoing URLs with the token are built internally and never surfaced to the MCP layer
- Error messages from the API that may reference the token URL are automatically redacted
Development
pnpm install
pnpm test # run all tests
pnpm test:watch # watch mode
pnpm typecheck # TypeScript check
pnpm build # build dist/
Running locally
THREADS_ACCESS_TOKEN=your_token pnpm build && node dist/index.js
Verify tool count
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
| THREADS_ACCESS_TOKEN=test node dist/index.js 2>/dev/null \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d['result']['tools']), 'tools')"