Read-optimized MCP server for Twitter/X, wrapping twscrape. BYO cookies, multi-account pool, agent-friendly tools.
Strong foundation with 8 well-named, read-only tools. All tools have descriptions (avg 120 chars) and complete input schemas with proper types and constraints. Tool names follow verb_noun pattern (read_*, search, auth_status, user_*). Parameters include min/max bounds and enums where appropriate. However, output schemas are not documented, LLMs cannot predict response structure. Error handling via _guard decorator is generic ('session may be rate-limited') rather than actionable recovery guidance. No per-tool risk annotations visible in schema definitions.
Check whether this server has an active X session, without exposing cookies.
Read quote-tweets of an X post (best-effort, via search:quoted_tweet_id). Coverage is partial, X does not expose a complete quotes endpoint.
Read the replies to an X post as markdown.
Read a full X thread as markdown: the root post, the author's self-thread, and top replies. Pass any tweet in the thread.
Read a single X post by URL or numeric id. Returns clean markdown.
Search X and return matching posts as markdown. product: "Latest" | "Top" | "Media". Supports X operators, e.g. from:user, to:user, has:media, -is:retweet, min_faves:100, since:2026-01-01.
Output schemas not documented. LLMs cannot predict response structure (fields, types, pagination). Formatters (tweet_to_md, thread_to_md, user_to_md) exist but their return types are not visible in tool definitions.
Error messages are generic and non-actionable. _guard() returns 'session may be rate-limited, logged out, or no account is available' without recovery guidance. Should specify: 'Rate-limited: retry in 15 min' or 'No account available: call auth_status or run twscrape-twitter-mcp accounts'.
Tool annotations present in code (_READ_ONLY_EXTERNAL, _READ_ONLY_LOCAL) but not visible in FastMCP tool registration. readOnlyHint=true should be declared on all 8 tools via schema metadata.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 70 | 2026-07-28+ | v2 |
Read an X user's profile by handle. Returns clean markdown. Pass the handle with or without a leading @.
Read a user's recent posts as markdown, newest first. Pass the handle with or without a leading @. Set include_replies=True to include the user's replies alongside their standalone posts.
Parameter descriptions lack format/constraint details. 'url_or_id' accepts both URLs and numeric IDs but description does not explain parsing rules or valid URL hosts. 'query' accepts X operators (from:, has:media, etc.) but this is buried in description, not formalized.
No pagination or result-limiting guidance in tool descriptions. search() and user_timeline() return up to 100 items but do not document whether results are paginated or if there is a next_cursor. LLMs cannot plan multi-page retrieval.