Read-only MCP server exposing Twitter/X bookmarks, home, search, tweets, and profiles to Claude.
Server has 7 well-named tools with complete input schemas and descriptions. All tools follow verb_noun naming (get_*, auth_*) and descriptions are 50-200 chars, meeting LLM-optimization baselines. However, output schemas are not formally documented in the code, only inferred from docstrings. Parameters lack enum constraints where applicable (e.g., 'feed' and 'mode' accept free-form strings). Error handling is minimal; no recovery guidance or actionable error messages visible. Security is sound (no secrets in params, read-only operations), but composition could be tighter, some tools like get_tweet and get_x_article overlap in scope.
Report whether a Twitter/X session is loaded and likely valid. Returns the session file path, the handle inferred from the filename, last-modified timestamp (proxy for last login), and an `authenticated` flag based on the presence of `auth_token` + `ct0` cookies in the file. This does NOT make a network request — to verify the session actually works against x.com, call any other tool. Session-expired errors there point back here.
Read the user's Twitter bookmarks, newest first. Args: limit: Max number of bookmarks to return (default 50). since_id: Stop scrolling once this tweet_id is observed. Useful for incremental fetches: pass the most recent tweet_id you've seen.
Read the user's home timeline. Args: limit: Max number of tweets to return (default 50). feed: "for_you" (algorithmic) or "following" (chronological from followed accounts). since_id: Stop once this tweet_id is observed.
Fetch a single tweet plus its conversation context. Args: id_or_url: Either the numeric tweet id (e.g. "1488816925400616964") or a full https://x.com/<handle>/status/<id> URL. include_replies: Include replies under the focal tweet. include_quote: Include the quoted tweet in the focal tweet's payload. Returns: ``{"focal": Tweet|None, "replies": [Tweet, ...]}``
Output schemas not formally documented. Docstrings describe return types informally ('list[dict]', 'Tweet|None') but no JSON Schema definitions visible in code. LLMs cannot reliably parse unstructured output.
'feed' parameter in get_home_timeline and 'mode' parameter in search_tweets accept free-form strings but should be enums. Current: type='string'. Should: enum=['for_you', 'following'] and enum=['top', 'latest']. Prevents LLM hallucination of invalid values.
No error handling guidance. Docstrings do not explain what errors can occur, whether they are retryable, or what the LLM should do next. E.g., SessionExpiredError is raised but not documented in tool descriptions.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 60 | 2026-07-28+ | v2 |
Fetch a user's public profile (bio, counts, pinned tweet id). Args: handle: Twitter handle without the leading "@".
Fetch the full body of a native X long-form article. Tweets that embed an X article only expose preview metadata (title + first paragraph) via ``tweet.x_article``. This tool navigates to the article's own page and returns the rendered body — both clean text (for LLM use) and the full HTML (for callers that want links/markup preserved). Args: id_or_url: The numeric article id (e.g. "1846123456789012345") or a full https://x.com/i/article/<id> URL. Returns: ``{article_id, url, title, body_text, body_html, char_count, media, body_markdown}`` or ``None`` if the article failed to render
Run a Twitter search. Args: query: Twitter search query (supports operators: from:, since:, etc.). limit: Max results to return (default 50). mode: "top" (relevance) or "latest" (chronological).
Pagination not fully exposed. get_bookmarks and get_home_timeline accept 'since_id' but do not return a 'next_cursor' or 'has_more' flag. LLMs cannot reliably determine when to stop fetching.
Scope/permission declarations missing. Tools do not declare what permissions they require (e.g., 'read:bookmarks', 'read:timeline'). Audit trail and least-privilege configuration not supported.