Skip to main content
Glama
@xcrap/mcp

@xcrap/mcp

Official
by XcrapCC

It wraps the public XCrap API. Twelve tools, one per endpoint, no credentials to configure. Use it hosted at https://xcrap.cc/mcp with nothing to install, or run it locally over stdio from npm — both serve the same tools.

NOTE

Always in step with the API. Every time an XCrap endpoint is added or changed, this server is updated and released with it, so the tools always match what the API can do.

Contents

Related MCP server: X Research MCP

How it works

sequenceDiagram
    autonumber
    actor You
    participant Client as Claude / Cursor
    participant MCP as @xcrapcc/mcp
    participant API as XCrap API
    participant X as X (public posts)
    You->>Client: "Unroll this thread and summarise it"
    Client->>MCP: xcrap_get_thread { url } (stdio)
    MCP->>API: GET /v1/thread?url=…&format=markdown
    API->>X: read the public thread
    X-->>API: posts
    API-->>MCP: compact Markdown
    MCP-->>Client: tool result (≤ 25,000 characters)
    Client-->>You: the summary

Quick start

Hosted: nothing to install

Point any client that speaks Streamable HTTP at:

https://xcrap.cc/mcp

No key, no account, no session. In Claude Code:

claude mcp add --transport http xcrap https://xcrap.cc/mcp

In Cursor (.cursor/mcp.json):

{
  "mcpServers": {
    "xcrap": { "url": "https://xcrap.cc/mcp" }
  }
}

In Claude Desktop or claude.ai, add it as a custom connector with that URL.

The hosted server is stateless and runs the same tools as the npm package. Each tool call is counted against your IP exactly like the API call it wraps (see Rate limits).

Local, over stdio

npx -y @xcrapcc/mcp

That is the whole installation. The server talks to https://xcrap.cc, and there is nothing to configure.

Claude Code

claude mcp add xcrap -- npx -y @xcrapcc/mcp

Make it available in every project rather than just this one:

claude mcp add xcrap --scope user -- npx -y @xcrapcc/mcp

Then check it connected:

claude mcp list

Claude Desktop

Edit claude_desktop_config.json and add the server:

OS

Config file

🍎 macOS

~/Library/Application Support/Claude/claude_desktop_config.json

🪟 Windows

%APPDATA%\Claude\claude_desktop_config.json

🐧 Linux

~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "xcrap": {
      "command": "npx",
      "args": ["-y", "@xcrapcc/mcp"]
    }
  }
}

Restart Claude Desktop — fully quit it first (Cmd + Q on macOS). The tools appear under the connectors icon in the prompt box.

Cursor

Create .cursor/mcp.json in the project (or ~/.cursor/mcp.json for every project):

{
  "mcpServers": {
    "xcrap": {
      "command": "npx",
      "args": ["-y", "@xcrapcc/mcp"]
    }
  }
}

Then enable xcrap in Settings → Tools & Integrations → MCP.

Any other MCP client

Use https://xcrap.cc/mcp if the client speaks Streamable HTTP. Otherwise run npx -y @xcrapcc/mcp, or node src/index.js from a clone of this repository, over stdio.

Tools

Tool

What it does

📄

xcrap_get_tweet

One post by URL or id: text, author, timestamp, metrics, media, poll, quote, community note, and any notice X shows on it. signals: true adds facts about its reach (age, For You window, new-author slot, engagement ratios). A dead post says why: deleted, protected, suspended, withheld.

🧵

xcrap_get_thread

Unrolls a whole thread from any post in it, in order, author's posts only.

👤

xcrap_get_user

A public profile: bio, location, website, join date, verification, follower counts.

📜

xcrap_get_user_tweets

A page of an account's posts, newest first, cursor-paginated.

🔎

xcrap_search

Full-text search over X posts with X's own operators, latest, top, photos or videos.

🗂️

xcrap_get_user_history

Up to 200 of an account's posts in one call, optionally inside a date window, with include_replies and include_reposts.

💬

xcrap_get_replies

The replies to a post, most liked or newest first (one page, no paging).

👥

xcrap_get_followers

One page of the accounts following an account, as profiles, cursor-paginated.

➡️

xcrap_get_following

One page of the accounts an account follows, as profiles, cursor-paginated.

🔥

xcrap_get_trends

What is trending on X right now, with post volumes.

🖼️

xcrap_list_media

Every image, video and GIF on a post, with dimensions, alt text and direct download URLs.

📦

xcrap_bulk

Up to 50 posts in a single call — the right tool for a list of links.

IMPORTANT

Every tool isread-only. Nothing here posts, likes, follows, or modifies anything on X.

Examples

Ask your client in plain language — it picks the tool:

You ask

The agent calls

"Unroll this thread and summarise the argument: https://x.com/jack/status/20"

xcrap_get_thread

"What has @NASA posted this week, images only?"

xcrap_get_user_tweets with media_only: true

"Get me the video from this post"

xcrap_list_media, then hands over the download_url

"Pull all 30 of these links into one summary"

xcrap_bulk (one call, not thirty)

"How many followers does @jack have?"

xcrap_get_user

"What are people on X saying about the Starship launch?"

xcrap_search with feed: "top"

"What are the replies saying about this post?"

xcrap_get_replies

"Everything @naval posted in March, reposts included"

xcrap_get_user_history with since, until and include_reposts: true

flowchart LR
    q["💬 Your question"] --> pick{"Which tool?"}
    pick -->|one link| t["xcrap_get_tweet"]
    pick -->|many links| b["xcrap_bulk"]
    pick -->|a thread| th["xcrap_get_thread"]
    pick -->|an account| u["xcrap_get_user · _user_tweets · _user_history"]
    pick -->|a topic| s["xcrap_search · xcrap_get_trends"]
    pick -->|a file| m["xcrap_list_media"]
    classDef accent fill:#f62d00,stroke:#141312,color:#ffffff
    class pick accent

Configuration

Variable

Default

Purpose

XCRAP_BASE_URL

https://xcrap.cc

API origin. Leave it unset; change it only to route requests through a proxy you control.

TIP

There is no API key. XCrap is free and unauthenticated, so the config blocks above are complete as they are.

Design notes

Every tool that renders posts defaults to format: "markdown", because a tool result is spent directly out of the model's context window and XCrap's Markdown rendering of a post is roughly a tenth the size of the same post as JSON — the JSON carries every null metric, every media variant and every entity offset, none of which a summarising model reads. Pass format: "json" when you genuinely need field-level access: numeric ids, media URLs, per-metric values. xcrap_list_media always returns JSON, because file URLs are field-level data.

No tool result can exceed it. When a response is cut, the model is told so explicitly, with the reason and the argument to change — a truncated answer that looks complete is worse than an error. Pagination cursors are lifted out before the cut so a truncated timeline can still be continued.

Status

What the model is told

404

The post is deleted, private, or never existed — and retrying will not help.

429

The retry-after window, and which endpoint budget was hit.

451

The account opted out of extraction and must not be worked around.

502

X could not be reached just now; usually transient.

XCrap caches posts for five days. Each result carries a one-line footer saying whether it came from the cache, so the model knows whether it is looking at live data.

Rate limits

Per IP, per endpoint, enforced by the XCrap API. The same budgets apply whether you use the hosted server or the local one: a hosted tool call is counted exactly like the API call it wraps.

Tool

Budget

xcrap_get_tweet, xcrap_get_user

45 / minute

xcrap_get_thread, xcrap_get_user_tweets

15 / minute

xcrap_get_replies, xcrap_get_followers, xcrap_get_following

15 / minute

xcrap_get_user_history

4 / 5 minutes

xcrap_search

10 / 15 minutes

xcrap_bulk

6 / 5 minutes (up to 50 posts each)

xcrap_list_media

20 / minute

xcrap_get_trends

90 / minute

TIP

Prefer onexcrap_bulk call over many xcrap_get_tweet calls: it is one request instead of N, and it runs them concurrently.

IMPORTANT

Running agents at scale? The Enterprise plan offers higher rate limits, dedicated capacity, custom endpoints and formats, priority support, and invoices or agreements — with the same rules (public accounts only). Write to hello@xcrap.cc.

Development

npm install
npm start                                              # run over stdio
npm run inspect                                        # MCP Inspector UI
npm run check                                          # syntax check

The tools are defined once, in src/tools.js. src/index.js runs them over stdio; the hosted server at https://xcrap.cc/mcp builds its server from the same file, so the two cannot drift.

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"cli","version":"1.0.0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
  | node src/index.js

Requires Node 20 or newer (built-in fetch, no HTTP dependency).

Ethics and limits

✅ It does

🚫 It will not

Read public posts, profiles, replies and follower lists

Read protected accounts, direct messages, or anything behind a login

Honour account opt-outs — a 451 is final

Route around an opt-out

Keep a short cache

Store anything beyond it

Repository

What it is

🟩 xcrap-node

The Node.js SDK — npm install @xcrapcc/sdk

🐍 xcrap-python

The Python SDK — pip install xcrap-sdk

📖 xcrap-docs

Guides, API reference, OpenAPI 3.1, llms.txt and skills.md

🏠 XcrapCC

Everything XCrap on GitHub

Agents that do not speak MCP can read skills.md, which teaches the whole API in one file, or llms.txt.


Available Tools

12 tools
xcrap_bulkFetch many X posts at onceA
Read-onlyIdempotent

Resolve up to 50 post URLs or ids in a single call.

This is the right tool whenever you have more than two or three links. One bulk call costs one request against a 10-per-5-minutes budget, while the same posts fetched individually cost one request each against a 60-per-minute budget — and bulk runs them concurrently, so it is several times faster.

Failures are per item, not per request: one dead link in a batch of fifty returns forty-nine posts and one error entry, so a single bad URL never loses the batch.

When to use this instead of the alternatives:

  • Use this for a list of links, a set of ids extracted from a document, or a batch job.

  • Use xcrap_get_tweet for a single post — bulk uses a cheaper, lighter source and returns slightly less detail per post (no media variants or entity offsets).

  • Use xcrap_get_thread for connected posts by one author; bulk does not know they are a thread.

Args:

  • urls (string[], required): 1-50 post URLs or numeric ids. Duplicates are removed by the server.

Returns markdown: a summary line of requested/succeeded/failed, then each post rendered in order, with an explicit error line for any that could not be resolved.

Errors: passing more than 50 URLs is rejected before any request is made — split the list into batches of 50.

Inputs: urls (required).

xcrap_get_followersList who follows an X accountA
Read-only

Fetch one page of the accounts following an X/Twitter account, each with its name, handle, bio, follower count and verification.

Use this for "who follows @x", "who does @x follow", or to find the other accounts in someone's circle. X decides the page size (usually a few dozen accounts); pass next_cursor to continue, and stop when it is null.

When to use this instead of the alternatives:

  • Use xcrap_get_user for one account's own profile and follower count, rather than the list of accounts.

Args:

  • handle (string, required): "jack", "@jack" or a profile URL.

  • cursor (string): the next_cursor from a previous call. Omit for the first page. Do not invent one.

  • format ('markdown' | 'json'): default 'markdown'.

Returns markdown: a heading, then one line per account — name, handle, follower count — with its bio underneath, and a "Next page" cursor line when there is more. Returns json: { handle, relation, count, next_cursor, users[ ] }.

Costs 20 calls/minute. Protected accounts return 404; accounts that opted out of XCrap are left out of the list.

Inputs: handle (required), cursor, format.

xcrap_get_followingList who an X account followsA
Read-only

Fetch one page of the accounts followed by an X/Twitter account, each with its name, handle, bio, follower count and verification.

Use this for "who follows @x", "who does @x follow", or to find the other accounts in someone's circle. X decides the page size (usually a few dozen accounts); pass next_cursor to continue, and stop when it is null.

When to use this instead of the alternatives:

  • Use xcrap_get_user for one account's own profile and follower count, rather than the list of accounts.

Args:

  • handle (string, required): "jack", "@jack" or a profile URL.

  • cursor (string): the next_cursor from a previous call. Omit for the first page. Do not invent one.

  • format ('markdown' | 'json'): default 'markdown'.

Returns markdown: a heading, then one line per account — name, handle, follower count — with its bio underneath, and a "Next page" cursor line when there is more. Returns json: { handle, relation, count, next_cursor, users[ ] }.

Costs 20 calls/minute. Protected accounts return 404; accounts that opted out of XCrap are left out of the list.

Inputs: handle (required), cursor, format.

xcrap_get_repliesGet the replies to an X postA
Read-only

Fetch the replies under an X/Twitter post, most liked first or newest first, with the post itself on top.

This is how you answer "what are people saying about this post", "what did the replies think" or "find the strongest pushback on this". Only direct replies come back — a reply to a reply belongs to its own conversation.

When to use this instead of the alternatives:

  • Use xcrap_get_tweet if you only need the post.

  • Use xcrap_get_thread for the author's own follow-up posts; replies by other people are not a thread.

Args:

  • url (string, required): the post's URL or bare numeric id.

  • sort ('top' | 'recent'): 'top' (default) for the most liked first, 'recent' for the newest first.

  • format ('markdown' | 'json'): default 'markdown'.

Returns markdown: a "Replies to" heading, the post, then each reply with its author, timestamp, text and metrics. Returns json: { tweet_id, tweet_url, sort, count, tweet{...}, replies[ ] }.

There is no paging: this is the single page X serves for the post, up to about a hundred replies. Costs 20 calls/minute. A 404 means the post is deleted, private or never existed.

Inputs: url (required), sort, format.

xcrap_get_threadUnroll an X threadA
Read-onlyIdempotent

Unroll a whole X/Twitter thread from any post in it, returning every post by the original author in order as one readable document.

This is the tool for "read this thread and summarise it". Give it the link the user pasted — first post, last post or anywhere in the middle — and it reconstructs the run. Replies by other people are excluded: a thread is one author's chain, not the surrounding conversation.

When to use this instead of the alternatives:

  • Use this when the link is part of a series of connected posts, or when a single post ends mid-thought.

  • Use xcrap_get_tweet if you only want the one post the URL points at (a thread costs more: 20 calls/minute).

  • Use xcrap_get_user_tweets to read an account's recent posts generally, rather than one connected chain.

Args:

  • url (string, required): any post in the thread, as a URL or numeric id.

  • max_tweets (number, 1-100): how many posts to unroll, default 25. Lower it if a response comes back truncated.

  • format ('markdown' | 'json'): default 'markdown'.

Returns (markdown): the author heading, then every post in order with its timestamp, text and metrics. Returns (json): { root_id, author{...}, count, truncated, tweets[ ] }. The 'truncated' flag is true when the thread is longer than max_tweets.

Note: threads are reconstructed from X's public data, so a very old thread may come back partial — 'truncated' and the post count tell you when that happened.

Inputs: url (required), format, max_tweets.

xcrap_get_tweetGet an X postA
Read-onlyIdempotent

Fetch one post (tweet) from X/Twitter by URL or numeric id, including its full text, author, timestamp, engagement metrics, attached media, poll, quoted post and community note.

Works without any X account, API key or login, and reads posts that x.com refuses to show logged-out visitors. Long-form posts are returned in full, not truncated at 280 characters.

When to use this instead of the alternatives:

  • Use this for ONE specific post. It is the cheapest tool here (60 calls/minute).

  • Use xcrap_get_thread if the post is the start or middle of a multi-post thread and you want the whole thread unrolled.

  • Use xcrap_bulk for several posts at once — it is one call instead of N and has a far larger effective budget.

  • Use xcrap_list_media if you only need the image or video files attached to the post.

Args:

Returns (markdown): a heading with the author's name and handle, the timestamp and permalink, the post text, and a line of metrics (likes, reposts, replies, quotes, bookmarks, views). Returns (json): { id, url, text, lang, created_at, created_timestamp, author{...}, metrics{likes,retweets,replies,quotes,bookmarks,views}, media[], poll, quote, replying_to, replying_to_status, community_note, possibly_sensitive, is_note_tweet, entities[], client }.

Errors: 404 means the post is deleted, private or never existed and retrying will not help; 451 means the author opted out of XCrap.

Inputs: url (required), format.

xcrap_get_userGet an X profileA
Read-onlyIdempotent

Fetch a public X/Twitter profile by handle: display name, bio, location, website, join date, verification status, avatar and banner URLs, and follower/following/post counts.

Use this to answer "who is @x", to check whether an account exists, or to get follower counts. It returns the profile only — not the account's posts.

When to use this instead of the alternatives:

  • Use xcrap_get_user_tweets to read what the account has actually posted.

  • Use xcrap_get_tweet if you have a link to a specific post rather than an account.

Args:

  • handle (string, required): "jack", "@jack" or "https://x.com/jack". Handles are 1-15 letters, digits or underscores; a display name will not work.

  • format ('markdown' | 'json'): default 'markdown'.

Returns (markdown): name and handle heading, bio, and a table of followers, following, posts, media count, join date, verification and website. Returns (json): { id, screen_name, name, url, description, location, website, avatar_url, banner_url, joined, verified, verified_type, protected, metrics{posts,followers,following,likes,media} }.

Errors: 404 means no such account, or it is suspended or private.

Inputs: handle (required), format.

xcrap_get_user_historyExport an X account's postsA
Read-onlyIdempotent

Fetch many of an account's posts in one call — walking its timeline page by page — optionally limited to a date window.

This is for "everything @x posted in March", "their last 200 posts" or "summarise what they said about Y this year". It replaces paging xcrap_get_user_tweets yourself, and it counts as one call against its budget however many pages it walks.

When to use this instead of the alternatives:

  • Use xcrap_get_user_tweets for a quick look at the latest posts.

  • Use xcrap_get_thread for one connected chain of posts.

Args:

  • handle (string, required): "jack", "@jack" or a profile URL.

  • max_posts (number, 1-200): stop after this many posts, default 50. The API allows up to 1,000, but a result that large will not fit in a context window; narrow the dates instead.

  • since (string): oldest post to include, as a date such as "2025-01-01".

  • until (string): newest post to include, as a date.

  • include_replies (boolean): default false. Set true to include the account's replies to other people.

Returns markdown: a "Post history" heading with the count and the window, then every post with its timestamp, permalink, text and metrics.

Costs 5 calls per 5 minutes — it is the most expensive tool here, so choose the window before calling rather than calling repeatedly. It takes about a second per twenty posts, and the further back a window sits, the patchier X's timeline is — an old window can legitimately come back empty.

Inputs: handle (required), since, until, max_posts, +1 more.

xcrap_get_user_tweetsGet an X account timelineA
Read-onlyIdempotent

Fetch a page of an account's posts, newest first, with text, timestamps and metrics for each.

This is how you answer "what has @x been posting about", "find their recent posts about Y" or "what did they say this week". Paging is cursor-based because a timeline moves while you read it: pass the next_cursor from the previous call to get the next page.

When to use this instead of the alternatives:

  • Use xcrap_get_user for the profile and follower counts instead of the posts.

  • Use xcrap_get_thread when the posts you want are one connected chain rather than a general feed.

Args:

  • handle (string, required): "jack", "@jack" or a profile URL.

  • count (number, 1-100): posts per page, default 20. Above ~40 the result is likely to be truncated.

  • cursor (string): the next_cursor from a previous call, to fetch the following page. Omit for the first page. Do not invent one.

  • exclude_replies (boolean): default true — the account's own posts only. Set false to include its replies to other people.

  • media_only (boolean): default false. Set true for only posts carrying images or video.

Returns markdown: a "Posts by @handle" heading, the post count, then each post with its timestamp, permalink, text and metrics. To page further, call xcrap_get_user_tweets again with the cursor returned by XCrap.

Costs 20 calls/minute — one call returning 50 posts is far cheaper than 50 calls to xcrap_get_tweet.

Inputs: handle (required), count, cursor, media_only, +1 more.

xcrap_list_mediaList media attached to an X postA
Read-onlyIdempotent

List every downloadable file attached to a post — photos, videos and GIFs — with type, dimensions, duration, alt text, every available quality variant, and a direct download URL for each.

Use this when the user wants the image or the video from a post rather than its text: "download the video from this tweet", "what images are in this post", "get me the alt text". The download URLs it returns stream the original file straight from X and can be handed to the user or fetched directly.

When to use this instead of the alternatives:

  • Use xcrap_get_tweet if you want the post's text and only need to know whether media exists.

  • Use this when you need the actual file URLs, resolutions or alt text.

Args:

  • url (string, required): post URL or numeric id.

Returns JSON (media metadata is field-level data, so this tool does not offer a markdown mode): { tweet_id, tweet_url, author, count, media: [ { id, type: "photo"|"video"|"gif", url, thumbnail_url, width, height, duration, format, alt_text, variants[ {url, container, bitrate} ], index, download_url } ] }

A post with no attachments returns count: 0 and an empty media array — that is a successful answer, not an error.

Inputs: url (required).

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A4.6/5.0

    Scored across 12 tools

    Disambiguation5/5

    Every tool targets a distinct retrieval mode: single post, bulk, thread, replies, user timeline/history, profile, followers/following, search, trends, and media. The 'when to use this instead of the alternatives' notes explicitly resolve the few overlapping surfaces, so an agent should not misselect.

    Naming Consistency4/5

    Nine tools follow the xcrap_get_<resource> pattern and all are lowercase snake_case with the xcrap_ prefix. The exceptions are xcrap_search, xcrap_bulk, and xcrap_list_media, which use bare verbs or list_ instead of get_. Overall the pattern is predictable, just slightly imperfect.

    Tool Count5/5

    12 tools is squarely in the well-scoped range for a read-only X/Twitter API. Each tool covers a distinct workflow and none feel like filler; the count supports both quick single-post lookups and bulk/history jobs.

    Completeness5/5

    For its stated purpose of reading X/Twitter public data, the surface is remarkably complete: posts (single, bulk, thread, replies), profiles, timelines, history, followers/following, search, trends, and media. There are no dead ends, and paging/error behavior is described consistently. Optional read surfaces like likes or list timelines are absent but are outside the apparent core scope.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      C
      quality
      C
      maintenance
      Enables AI agents to search, read user profiles, timelines, media, follow threads, track trends, and manage accounts on X/Twitter via GraphQL, without browser automation or paid API keys.
      100
      11
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Enables read-only research on public X data through tools for posts, threads, profiles, search, trends, collections, and saved-result analysis using free public APIs and optional sessions.
      8
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Provides read-only access to public X (Twitter) data, including profiles, tweets, timelines, threads, followers, and search, for developers and AI agents.
      1
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to read public X (Twitter) data without the paid official API, including tweet and user search, profiles, timelines, media, replies, retweeters, followers, lists, and trends. All tools are read-only and rotate across multiple scraping accounts with proxy and rate-limit support.
      MIT