threads-mcp
# threads-mcp
A Model Context Protocol (MCP) server for the [Threads API](https://developers.facebook.com/docs/threads). 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.
1. Go to [developers.facebook.com/tools/explorer](https://developers.facebook.com/tools/explorer)
2. Select your **Threads App** from the app dropdown (or create one at [developers.facebook.com/apps](https://developers.facebook.com/apps) with the Threads product)
3. In the **Threads Tester**, generate a short-lived token
4. To get a **long-lived token** (60 days), call:
```bash
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"
```
5. To **refresh** a long-lived token before it expires:
```bash
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
```bash
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
```bash
# Install globally
npm install -g threads-mcp
# Or run directly
npx threads-mcp
```
Or build from source:
```bash
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):
```json
{
"mcpServers": {
"threads": {
"command": "npx",
"args": ["-y", "threads-mcp"],
"env": {
"THREADS_ACCESS_TOKEN": "your_access_token_here"
}
}
}
}
```
Or if installed globally:
```json
{
"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:
```json
{
"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_search` and `threads_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_limit` to 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_TOKEN` is **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
```bash
pnpm install
pnpm test # run all tests
pnpm test:watch # watch mode
pnpm typecheck # TypeScript check
pnpm build # build dist/
```
### Running locally
```bash
THREADS_ACCESS_TOKEN=your_token pnpm build && node dist/index.js
```
### Verify tool count
```bash
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')"
```
TDQS
Scored across 26 tools
Each tool targets a distinct action and resource, with clear descriptions that differentiate overlapping concepts like get_thread vs get_conversation vs get_replies. No two tools are easily confused.
All tools follow a consistent verb_noun pattern in snake_case (e.g., create_text_post, get_thread_insights). No mixing of styles or ambiguous verbs.
With 26 tools, the set is on the higher end but each tool serves a specific and necessary function for the Threads API, covering posting, reading, searching, analytics, and moderation without unnecessary redundancy.
The tool surface covers core CRUD and lifecycle operations for posts, plus searching and analytics. A notable gap is the lack of an update/edit tool for posts, but most workflows are supported.