Skip to main content
Glama

Spectre is an MCP server that gives AI agents 104 tools for X/Twitter automation — from search and posting to DMs, lists, and communities. Under the hood, it talks directly to X's internal GraphQL and REST APIs. No browser to spin up, no Puppeteer to maintain, no DOM scraping that breaks on UI changes.

Spectre

XActions

twikit

Architecture

Direct GraphQL/REST

Puppeteer (headless browser)

Python API wrapper

Speed

<1s per request

3–10s (browser startup)

~1s per request

Memory

~10 MB

~200 MB+ (Chromium)

~10 MB

MCP Server

✓ 104 tools

~50 API tools

✗ None

Account Pool

✓ Multi-account auto-rotation

✗ Single auth_token

✗ Single session

Browser Required

✗ Never

✓ Always

✗ Never

DOM Breakage Risk

✗ None

~ breaks on UI changes

✗ None

Media Upload

✓ Cookie-based (no API keys)

~ requires API keys

✗

Lists

✓ Full CRUD + members + subscribe

✗

✗

Drafts & Scheduled

✓ Full CRUD

~ Basic

✗

Bookmark Folders

✓ Full CRUD + timeline

✗

✗

DM Search

✓ All / groups / people

✗

✗

Community Notes

✓ Read + rate

✗

✗

Highlights

✓ Create, delete, get

✗

✗

Notifications

✓ Full timeline

✗

✗

Language

Python

JavaScript

Python


1. Install

pipx install spectre-mcp    # or: uv tool install spectre-mcp

2. Add Your X Account

Extract cookies from your browser:

  1. Open x.com and make sure you're logged in

  2. Open DevTools (F12 or Ctrl+Shift+I)

  3. Go to Storage → Cookies → select https://x.com

  4. Find and copy these two values:

    • auth_token — long hex string (e.g. a1b2c3d4...)

    • ct0 — 160-character hex string

spectre add myaccount "auth_token=a1b2c3d4...; ct0=e5f6a7b8..."

Tip: ct0 is exactly 160 hex characters. Double-check you copied the full value — partial cookies will fail silently.

3. Configure Your MCP Client

Add to your MCP client config (~/.hermes/config.yaml, claude_desktop_config.json, .cursor/mcp.json, or equivalent):

{
  "mcpServers": {
    "spectre": {
      "command": "uvx",
      "args": ["spectre-mcp"]
    }
  }
}

For client-specific setup (Hermes skill, Claude, Cursor, Python), see Integrations.

No uv? Install it: curl -LsSf https://astral.sh/uv/install.sh | sh Or use python3 -m spectre.server to run from a local clone.

4. Call a Tool — IDs Are Strings

Every tool that takes an X ID (tweet_id, user_id, list_id, community_id, reply_to, quote_tweet) takes it as a string:

get_tweet("2111332908657148356")

X IDs are 64-bit integers. Most MCP clients and model APIs parse JSON numbers as IEEE-754 doubles, which rounds anything above 2^53 — 2111332908657148356 silently becomes 2111332908657148416, and the tool reports a perfectly good tweet as "not found or deleted". Passing the ID as a string removes the round-trip entirely, so the server sees the exact ID the model meant. A full https://x.com/... URL works too, and a plain integer is still accepted for backwards compatibility.



License

MIT

Available Tools

104 tools
add_list_memberA

Add a user to an X/Twitter list.

Inputs: list_id (required), user_id (required). Returns: result

add_tweet_to_folderB

Add a bookmarked tweet to a folder.

Inputs: tweet_id (required), folder_id (required). Returns: result

block_userB

Block a user on X/Twitter.

Inputs: user_id (required). Returns: result

bookmark_tweetC

Bookmark a tweet.

Inputs: tweet_id (required). Returns: result

clear_all_bookmarksA

⚠️ DESTRUCTIVE — Delete ALL bookmarks. Cannot be undone.

Inputs: no named parameters. Returns: result

create_bookmark_folderB

Create a bookmark folder.

Inputs: name (required). Returns: result

create_draftA

Save a tweet draft (not published).

Inputs: text (required). Returns: result

create_highlightB

Add tweets to your profile highlights section.

Inputs: tweet_ids (required). Returns: result

create_listB

Create a new X/Twitter list.

Inputs: name (required), description. Returns: result

delete_bookmark_folderC

Delete a bookmark folder.

Inputs: folder_id (required). Returns: result

delete_draftB

Delete a draft tweet.

Inputs: tweet_id (required). Returns: result

delete_highlightB

Remove a highlight from your profile.

Inputs: highlight_id (required). Returns: result

delete_listC

Delete an X/Twitter list.

Inputs: list_id (required). Returns: result

delete_profile_bannerA

⚠️ DESTRUCTIVE — Remove the profile banner/header image.

WARNING: This immediately removes your banner image.

Returns: Confirmation JSON.

Inputs: no named parameters. Returns: result

delete_scheduled_tweetB

Delete a scheduled tweet.

Inputs: tweet_id (required). Returns: result

delete_tweetB

Delete a tweet you posted.

Inputs: tweet_id (required). Returns: result

dm_block_userA

Block a user from sending you DMs.

Inputs: user_id (required). Returns: result

dm_unblock_userB

Unblock a user from DMs.

Inputs: user_id (required). Returns: result

edit_bookmark_folderB

Rename a bookmark folder.

Inputs: name (required), folder_id (required). Returns: result

edit_draftC

Edit an existing draft tweet.

Inputs: text (required), draft_id (required). Returns: result

edit_scheduled_tweetC

Edit an existing scheduled tweet.

Inputs: text (required), execute_at (required), scheduled_id (required). Returns: result

follow_topicC

Follow a topic on X/Twitter.

Inputs: topic_id (required). Returns: result

follow_userB

Follow a user on X/Twitter.

Inputs: user_id (required). Returns: result

get_account_settingsA

Get the authenticated account's settings (language, timezone, country, etc.).

Returns: JSON with account settings including language, country, timezone, protected status, etc.

Inputs: no named parameters. Returns: result

get_blocked_accountsB

List all accounts you've blocked.

Inputs: limit. Returns: result

get_bookmark_foldersA

Get all bookmark folders.

Returns: JSON with list of bookmark folders.

Inputs: no named parameters. Returns: result

get_bookmark_folder_timelineC

Get tweets inside a specific bookmark folder.

Inputs: folder_id (required), limit. Returns: result

get_bookmarksA

Get the authenticated user's bookmarked tweets.

Inputs: limit. Returns: result

get_community_infoB

Get details about an X/Twitter community.

Inputs: community_id (required). Returns: result

get_community_notesC

Get community notes on a tweet.

Inputs: tweet_id (required). Returns: result

get_community_tweetsB

Get tweets from an X/Twitter community.

Inputs: community_id (required), limit. Returns: result

get_dm_conversationB

Get messages in a direct message conversation.

Inputs: conversation_id (required), limit. Returns: result

get_dm_inboxB

Get DM inbox — list recent direct message conversations.

Inputs: limit. Returns: result

get_dm_mutedC

Get muted DM conversations.

Inputs: limit. Returns: result

get_draftsA

Get all draft tweets.

Returns: JSON with list of drafts.

Inputs: no named parameters. Returns: result

get_favoritersC

Get users who liked a tweet.

Inputs: tweet_id (required), limit. Returns: result

get_followersC

Get a user's followers.

Inputs: username (required), limit. Returns: result

get_followers_you_knowC

Get mutual followers (followers you know).

Inputs: user_id (required), limit. Returns: result

get_followingC

Get who a user follows.

Inputs: username (required), limit. Returns: result

get_home_timelineB

Get the authenticated user's home timeline feed.

Inputs: limit. Returns: result

get_list_membersA

Get members of an X/Twitter list.

Inputs: list_id (required), limit. Returns: result

get_list_membershipsC

Get lists a user is a member of.

Inputs: user_id (required), limit. Returns: result

get_list_ownershipsC

Get lists owned by a user.

Inputs: user_id (required), limit. Returns: result

get_list_subscribersC

Get subscribers of a list.

Inputs: list_id (required), limit. Returns: result

get_list_timelineC

Get tweets from an X/Twitter list.

Inputs: list_id (required), limit. Returns: result

get_muted_accountsA

List all accounts you've muted.

Inputs: limit. Returns: result

get_notificationsC

Get notifications timeline.

Inputs: limit. Returns: result

get_retweetersB

Get users who retweeted a tweet.

Inputs: tweet_id (required), limit. Returns: result

get_scheduled_tweetsA

Get all scheduled tweets.

Returns: JSON with list of scheduled tweets.

Inputs: no named parameters. Returns: result

get_similar_postsC

Get similar/related posts to a tweet.

Inputs: tweet_id (required), limit. Returns: result

get_threadA

Get the full conversation thread a tweet belongs to.

Inputs: tweet_id (required), limit. Returns: result

get_topic_infoC

Get topic details by ID.

Inputs: topic_id (required). Returns: result

get_tweetB

Get a single tweet by its ID.

Inputs: tweet_id (required). Returns: result

get_tweet_edit_historyC

Get edit history of a tweet.

Inputs: tweet_id (required). Returns: result

get_tweet_repliesC

Get replies to a tweet.

Inputs: tweet_id (required), limit. Returns: result

get_userA

Get a user's X/Twitter profile by @handle.

Inputs: username (required). Returns: result

get_user_highlightsA

Get a user's profile highlight tweets.

Inputs: user_id (required), limit. Returns: result

get_user_likesC

Get a user's liked tweets.

Inputs: user_id (required), limit. Returns: result

get_user_mediaB

Get a user's media tweets (photos, videos, GIFs).

Inputs: username (required), limit. Returns: result

get_user_tweetsB

Get a user's recent tweets.

Inputs: username (required), limit. Returns: result

get_user_tweets_and_repliesC

Get a user's tweets and replies.

Inputs: username (required), limit. Returns: result

get_verified_followersB

Get Blue-verified followers of a user.

Inputs: user_id (required), limit. Returns: result

join_communityB

Join an X/Twitter community.

Inputs: community_id (required). Returns: result

leave_communityB

Leave an X/Twitter community.

Inputs: community_id (required). Returns: result

like_tweetC

Like a tweet.

Inputs: tweet_id (required). Returns: result

list_accountsA

List all accounts in the pool with their status.

Shows username, state (active/error/locked), and any error messages. Use this to check which accounts are available before operations.

Returns: JSON array of accounts with status details.

Inputs: no named parameters. Returns: result

mute_userB

Mute a user on X/Twitter.

Inputs: user_id (required). Returns: result

pin_replyC

Pin a reply to a conversation.

Inputs: tweet_id (required). Returns: result

pin_tweetA

⚠️ DESTRUCTIVE — Pin a tweet to your profile (replaces any existing pinned tweet).

WARNING: If you already have a pinned tweet, it will be unpinned automatically. Only one tweet can be pinned at a time.

Inputs: tweet_id (required). Returns: result

pool_statusA

Check account pool health — how many accounts are active, locked, or errored.

Returns: JSON with pool statistics and per-account status.

Inputs: no named parameters. Returns: result

post_tweetC

Post a new tweet on X/Twitter.

Inputs: text (required), reply_to, media_ids, quote_tweet. Returns: result

rate_community_noteB

Rate a community note as helpful or not helpful.

Inputs: rating (required), note_id (required). Returns: result

remove_accountC

Remove an account from the pool.

Inputs: username (required). Returns: result

remove_followerC

⚠️ DESTRUCTIVE — Remove a follower from your account.

Inputs: user_id (required). Returns: result

remove_list_memberA

Remove a user from an X/Twitter list.

Inputs: list_id (required), user_id (required). Returns: result

remove_tweet_from_folderB

Remove a tweet from a bookmark folder.

Inputs: tweet_id (required), folder_id (required). Returns: result

retweetC

Retweet a tweet.

Inputs: tweet_id (required). Returns: result

schedule_tweetA

Schedule a tweet for future posting.

Inputs: text (required), execute_at (required), reply_to. Returns: result

search_bookmarksB

Search bookmarks by text.

Inputs: query (required), limit. Returns: result

search_dmC

Search direct messages by text.

Inputs: query (required), limit. Returns: result

search_dm_groupsC

Search DMs in group conversations.

Inputs: query (required), limit. Returns: result

search_dm_peopleC

Search for people in DMs.

Inputs: query (required), limit. Returns: result

search_usersB

Search X/Twitter for users by name or keyword.

Inputs: query (required), limit. Returns: result

send_dmB

Send a direct message to a user.

Inputs: text (required), user_id (required). Returns: result

set_active_accountA

Set a specific account as the primary account for all operations.

The named account will be used first for reads and writes. If it gets rate-limited, the pool falls back to other active accounts.

Inputs: username (required). Returns: result

set_auto_rotateA

Enable or disable automatic account rotation on rate limits.

When enabled (default): if the current account hits a rate limit, Spectre automatically switches to the next available account. The agent sees a note that rotation happened.

When disabled: only the account set via set_active_account() is used. Rate limits are returned as errors instead of rotating silently. Use this when you're managing a specific account and don't want operations accidentally going through a different account.

Inputs: enabled (required). Returns: result

subscribe_listC

Subscribe to a list.

Inputs: list_id (required). Returns: result

unblock_userB

Unblock a user on X/Twitter.

Inputs: user_id (required). Returns: result

unbookmark_tweetC

Remove a bookmark.

Inputs: tweet_id (required). Returns: result

unfollow_topicB

Unfollow a topic on X/Twitter.

Inputs: topic_id (required). Returns: result

unfollow_userB

Unfollow a user on X/Twitter.

Inputs: user_id (required). Returns: result

unlike_tweetB

Unlike a tweet.

Inputs: tweet_id (required). Returns: result

unmute_userA

Unmute a user on X/Twitter.

Inputs: user_id (required). Returns: result

unpin_replyB

Unpin a reply from a conversation.

Inputs: tweet_id (required). Returns: result

unpin_tweetB

Unpin a tweet from your profile.

Inputs: tweet_id (required). Returns: result

unretweetB

Undo a retweet.

Inputs: tweet_id (required). Returns: result

unsubscribe_listC

Unsubscribe from a list.

Inputs: list_id (required). Returns: result

update_listA

Update an X/Twitter list's name/description.

Inputs: name (required), list_id (required), description. Returns: result

update_profileA

⚠️ DESTRUCTIVE — Update the authenticated account's profile info.

WARNING: This immediately changes your public profile on X. All fields are optional — only provide the ones you want to change. Empty strings are ignored.

Inputs: bio, name, website, location. Returns: result

update_profile_bannerA

⚠️ DESTRUCTIVE — Change the profile banner/header image.

WARNING: This immediately replaces your current banner. Recommended size: 1500x500px. Supported: jpg, png, gif (max 5MB).

Inputs: file_path (required). Returns: result

update_profile_imageA

⚠️ DESTRUCTIVE — Change the profile avatar image.

WARNING: This immediately replaces your current profile picture. Supported: jpg, png, gif (max 2MB recommended).

Inputs: file_path (required). Returns: result

upload_mediaA

Upload an image or video for use in tweets.

Uses cookie-based auth. No API keys needed. Supports: jpg, png, gif, webp, mp4, mov (up to 5MB images, 512MB video).

Inputs: file_path (required). Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.9/5.0

    Scored across 104 tools

    Disambiguation3/5

    Most tools have distinct resource-action targets, but several pairs overlap meaningfully (list_accounts vs pool_status, get_user_tweets vs get_user_tweets_and_replies, get_muted_accounts vs get_dm_muted). The high number of choices increases misselection risk, though the descriptions usually clarify boundaries.

    Naming Consistency4/5

    The server consistently uses snake_case verb_noun names like get_tweet, post_tweet, create_list, and unlike_tweet. Minor deviations exist—remove vs delete, pool_status instead of get_pool_status, and phrase-like names such as get_followers_you_know—but the overall pattern remains predictable.

    Tool Count1/5

    104 tools is an extreme count for an MCP server and creates a heavy selection burden for agents. Even for a broad X/Twitter domain, many niche actions could be consolidated through parameters or grouped resources, so the surface is clearly oversized.

    Completeness4/5

    The surface covers nearly the full X/Twitter lifecycle: reading, posting, deleting tweets, engagement, DMs, lists, bookmarks, communities, profiles, scheduling, and drafts. Minor gaps exist—such as no way to add accounts to the pool or fetch the current authenticated profile directly—but these are workable and do not undermine core workflows.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      Not graded
      maintenance
      Connects AI assistants to Twitter/X using cookie-based authentication to read timelines, search tweets, and perform actions like posting and liking. It leverages Twitter's internal GraphQL API to provide full functionality without requiring a developer account.
      19 npm
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI agents to interact with Twitter/X through Playwright browser automation without requiring an official API key. It provides tools for posting content, searching tweets, reading feeds, and managing social interactions like follows and likes.
      4
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Provides AI agents and coding assistants with Twitter data access including tweets, user profiles, followers, and search functionality.
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to fully automate X/Twitter interactions including searching, posting, engaging, and managing multiple accounts without paid API keys.
      MIT