{
  "markdown": "# x-mcp-ai — X (Twitter) MCP Server\n\n<div align=\"center\">\n\n| | | | | | |\n|:--:|:--:|:--:|:--:|:--:|:--:|\n| [![npm](https://img.shields.io/npm/v/x-mcp-ai?style=flat-square)](https://www.npmjs.com/package/x-mcp-ai) | [![CI](https://img.shields.io/github/actions/workflow/status/IvanBBaev/x-mcp/ci.yml?branch=main&style=flat-square)](https://github.com/IvanBBaev/x-mcp/actions/workflows/ci.yml) | [![tools](https://img.shields.io/badge/tools-41-blue?style=flat-square)](#tools) | [![node](https://img.shields.io/badge/node-%3E%3D22-brightgreen?style=flat-square)](https://nodejs.org) | [![MCP](https://img.shields.io/badge/MCP-server-orange?style=flat-square)](https://modelcontextprotocol.io) | [![license](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE) |\n\n</div>\n\nAn [MCP](https://modelcontextprotocol.io) server that exposes the **X (Twitter) API v2** to\nMCP clients — Claude Code, Claude Desktop, VS Code, Cursor, or any MCP-compatible agent — as\na curated set of **typed tools**, gated by a two-axis policy model and aware of the 2026\npay-per-use pricing so an agent can never quietly overspend.\n\n> **Status: pre-1.0, under active development, published on npm as\n> [`x-mcp-ai`](https://www.npmjs.com/package/x-mcp-ai)** (currently `0.8.0`, published from\n> CI with npm provenance). Pin an exact version while the project is on `0.x`\n> ([Setup](#setup)). **41 tools across 12 packages** are registered today; the full designed\n> surface lives in [`docs/03-tool-catalog.md`](docs/03-tool-catalog.md) and has landed\n> in full. The public API is unstable until `1.0.0`.\n\nContents: [Quick demo](#quick-demo) · [Features](#features) · [Requirements](#requirements) ·\n[Setup](#setup) · [Configure credentials](#configure-credentials) · [Cost](#cost) ·\n[Run / debug](#run--debug) · [Develop](#develop) · [Tools](#tools) ·\n[Resources](#resources) · [Prompts](#prompts) · [Project structure](#project-structure) ·\n[Security notes](#security-notes) · [Data handling](#data-handling) ·\n[Documentation](#documentation) · [Support](#support) · [Trademark](#trademark)\n\n## Quick demo\n\nOnce the server is wired into your MCP client, you drive it in natural language and the\nmodel picks the tool. Three representative asks:\n\n```jsonc\n// 1. Read (default read-only preset — no writes possible)\n// \"What are people saying about the Model Context Protocol this week?\"\n{\n  \"tool\": \"x_search_recent\",\n  \"arguments\": { \"query\": \"\\\"model context protocol\\\" -is:retweet lang:en\", \"max_results\": 25 }\n}\n```\n\n```jsonc\n// 2. Engage (requires the `engage` preset or an explicit write:engagement allow)\n// \"Like that launch post for me.\"\n{\n  \"tool\": \"x_like_set\",\n  \"arguments\": { \"post_id\": \"1899…\", \"action\": \"like\" }\n}\n```\n\n```jsonc\n// 3. Publish (requires the `publish` preset or write:content)\n// \"Post: 'Shipping x-mcp-ai today.' — mind the cost.\"\n// Every result carries cost_usd + session_total_usd; a URL in the text raises the price 13×.\n{\n  \"tool\": \"x_post_create\",\n  \"arguments\": { \"text\": \"Shipping x-mcp-ai today.\" }\n}\n```\n\n## Features\n\n- **41 tools across 12 packages** over the X API v2 — read posts, users and timelines,\n  search (recent and full-archive), engage, publish, manage lists, upload media, walk the\n  social graph, and read/send DMs behind an explicit opt-in.\n- **Two-axis policy model** (`operation:domain`) with five presets — `read-only` (default),\n  `engage`, `publish`, `manage`, `full`. Writes are opt-in; **deny beats allow beats\n  preset**, per cell. Direct-message cells are double-locked: `read:dm`/`write:dm` are in\n  **no** preset, not even `full`.\n- **Cost awareness built in.** Since 2026-02-06 the X API v2 is pay-per-use. Every result\n  reports its own `cost_usd` and the running `session_total_usd`; an operator-set\n  `X_MCP_CREDIT_BUDGET` with `X_MCP_BUDGET_MODE=hard` refuses calls that would exceed it,\n  and the model cannot raise the cap.\n- **Two auth modes** — OAuth 2.0 PKCE user context (primary, rotating refresh tokens,\n  single-flight refresh) and app-only bearer for read-only deployments.\n- **Security-first defaults** — host-scoped `Authorization` header, redirects never followed\n  on token-bearing requests, `0600` token file written with `O_NOFOLLOW`/`O_EXCL`,\n  untrusted-content marking on returned text, and media upload default-deny outside a\n  realpath-contained `X_MCP_MEDIA_DIR`.\n- **Typed failures.** Eleven error classes, each carrying `retryable` and\n  `fix: \"agent\" | \"operator\"`, so the model retries what is retryable and escalates what is\n  not.\n- **Structured output.** Every tool advertises a JSON-Schema `outputSchema` and returns\n  `structuredContent` alongside the text block.\n- **Availability class-gating**, live per-endpoint rate-limit tracking (including the\n  24-hour app cap on post creation), cursor pagination, and compact result rendering.\n\n## Requirements\n\n- **Node.js >= 22** (see [`.nvmrc`](.nvmrc)).\n- An **X developer account and app** with an OAuth 2.0 client (Client ID; Client Secret only\n  for confidential clients). App-only mode needs a bearer token instead.\n- **Prepaid X API credits** — the API bills per read and per write (see [Cost](#cost)).\n\n## Setup\n\nThe recommended install is the published package, pinned to an exact version while the\nproject is on `0.x` — nothing to clone or build:\n\n```bash\nnpx -y x-mcp-ai@0.8.0 doctor   # sanity check; makes no billable calls\n```\n\nThen point your MCP client at it:\n\n```jsonc\n// claude_desktop_config.json (Claude Desktop) / .mcp.json (Claude Code) / .cursor/mcp.json\n{\n  \"mcpServers\": {\n    \"x\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"x-mcp-ai@0.8.0\"],\n      \"env\": {\n        \"X_MCP_AUTH_MODE\": \"oauth2\",\n        \"X_MCP_CLIENT_ID\": \"your-oauth2-client-id\",\n        \"X_MCP_POLICY\": \"read-only\",\n        \"X_MCP_CREDIT_BUDGET\": \"5.00\",\n        \"X_MCP_BUDGET_MODE\": \"hard\"\n      }\n    }\n  }\n}\n```\n\nRunning from a local checkout instead? Use `\"command\": \"node\"` with\n`\"args\": [\"/abs/path/to/x-mcp/build/src/index.js\"]` and the same `env` map.\n\nClaude Code from the CLI:\n\n```bash\nclaude mcp add x --env X_MCP_POLICY=read-only -- npx -y x-mcp-ai@0.8.0\n```\n\n**Per-client instructions** — Claude Desktop, Claude Code, VS Code (`.vscode/mcp.json`),\nCursor and MCP Inspector — are in\n[`docs/10-operator-guide.md`](docs/10-operator-guide.md) §4, together with the `authorize`\nflow and ready-made env recipes.\n\n### From source (development)\n\nStill fully supported — build the entry point and spawn it with `node` instead of `npx`:\n\n```bash\ngit clone https://github.com/IvanBBaev/x-mcp.git\ncd x-mcp\nnpm ci\nnpm run build          # tsc → build/src/index.js\nnode build/src/index.js doctor   # sanity check; makes no billable calls\n```\n\n## Configure credentials\n\nThe server never prompts interactively; all configuration comes from environment variables\n(canonical table: [`docs/02-architecture.md`](docs/02-architecture.md) §4; a starting point:\n[`.env.example`](.env.example)).\n\n**Auth modes** (`X_MCP_AUTH_MODE`):\n\n- `oauth2` *(default)* — OAuth 2.0 with PKCE. Run the one-time authorization flow with the\n  `authorize` subcommand; tokens land in `X_MCP_TOKEN_FILE` and are refreshed automatically.\n- `app-only` — application-only bearer token (`X_MCP_BEARER_TOKEN`); read endpoints only, no\n  user context.\n\n```bash\nX_MCP_AUTH_MODE=oauth2 X_MCP_CLIENT_ID=… node build/src/index.js authorize\n```\n\n### Environment variables\n\n| Variable | Default | Secret | Purpose |\n|---|---|:--:|---|\n| `X_MCP_AUTH_MODE` | `oauth2` | | `oauth2` \\| `app-only`. |\n| `X_MCP_CLIENT_ID` | | | OAuth 2.0 client ID (required for `authorize` and refresh). |\n| `X_MCP_CLIENT_SECRET` | | ✅ | OAuth 2.0 client secret (confidential clients only). |\n| `X_MCP_BEARER_TOKEN` | | ✅ | App-only bearer token; valid only with `app-only`. |\n| `X_MCP_TOKEN_FILE` | OS-resolved | | Path to the rotating OAuth 2.0 token store (`~` expanded). |\n| `X_MCP_TOKEN_KEYCHAIN` | `0` | | `1` → store tokens in the OS keychain (macOS `security`, Linux `secret-tool`). Mutually exclusive with `X_MCP_TOKEN_FILE`. |\n| `X_MCP_POLICY` | `read-only` | | Preset: `read-only` \\| `engage` \\| `publish` \\| `manage` \\| `full`. |\n| `X_MCP_POLICY_ALLOW` | | | Comma-separated `operation:domain` cells to add. |\n| `X_MCP_POLICY_DENY` | | | Comma-separated cells to remove (wins over allow and preset). |\n| `X_MCP_HIDE_DENIED` | `0` | | `1` → drop denied tools from registration entirely. |\n| `X_MCP_CREDIT_BUDGET` | | | Session spend cap, USD (e.g. `5.00`). Unset = no cap. |\n| `X_MCP_BUDGET_MODE` | `warn` | | `warn` \\| `hard`. |\n| `X_MCP_AVAILABILITY` | | | Comma-separated availability classes to enable (`pilot`, `premium-user`, `enterprise`). |\n| `X_MCP_MEDIA_DIR` | | | Directory uploads must `realpath` inside (media default-deny). |\n| `X_MCP_PROFILES_FILE` | | | Multi-account profiles file. |\n| `X_MCP_PROFILE` | | | Active profile name (required with a profiles file). |\n| `X_MCP_BASE_URL` | `https://api.x.com` | | API base URL; must be `https://` and `*.x.com`. |\n| `X_MCP_ALLOW_INSECURE_BASE_URL` | `0` | | `1` → permit a non-`x.com` base URL (testing only). |\n| `X_MCP_TIMEOUT_MS` | `30000` | | Per-request timeout, milliseconds. |\n| `X_MCP_LOG_LEVEL` | `info` | | `silent` \\| `error` \\| `info` \\| `debug`. |\n\nAny other `X_MCP_*` variable is ignored with a startup warning — that is the typo detector.\nEvery fatal configuration error names the variable at fault.\n\n### Two-axis access policy\n\nEvery tool maps to one **policy cell** — an `operation:domain` pair. Operations escalate\n`read` → `write` → `destructive`; domains are `content`, `user`, `account`, `engagement`,\n`social-graph`, `moderation`, `dm`. A preset unlocks a set of the 12 valid cells;\n`X_MCP_POLICY_ALLOW` adds cells, `X_MCP_POLICY_DENY` removes them, and\n**deny > allow > preset**.\n\n| Preset | Grants | Callable tools |\n|---|---|--:|\n| `read-only` *(default)* | all `read:*` cells **except** `read:dm` | 21 |\n| `engage` | read-only **+** `write:engagement` | 26 |\n| `publish` | engage **+** `write:content`, `write:moderation` | 32 |\n| `manage` | publish **+** `destructive:content` | 34 |\n| `full` | every non-DM cell — adds `write:social-graph`, `destructive:social-graph` | 37 |\n\n> **DM cells are never in a preset — not even `full`.** `read:dm` and `write:dm` must be\n> granted explicitly via `X_MCP_POLICY_ALLOW` (all 41 tools callable). Their unlock hint is\n> deliberately withheld from policy errors, as it is for every other sensitive cell.\n> Denied tools stay registered but annotated `(disabled by policy <preset>)` unless\n> `X_MCP_HIDE_DENIED=1`.\n\nNote that `manage` grants destructive **content** operations only — follow/mute/block need\n`full` or an explicit `write:social-graph` / `destructive:social-graph` allow.\n\n## Cost\n\n> **Pay-per-use is the only pricing model.** X retired the Free/Basic/Pro subscription tiers\n> for new developers on **2026-02-06**; every read and write draws down prepaid credits.\n> Since **2026-04-16**, a post whose text contains a **URL costs $0.20 instead of $0.015 —\n> 13×**. Set `X_MCP_CREDIT_BUDGET` before pointing an agent at a real account.\n\nIndicative rates (verified 2026-07-22): post reads ~$0.005 each, user lookups and\nfollower/following reads ~$0.010, own-data reads ~$0.001, DM events ~$0.010, post create\n$0.015 (or $0.20 with a URL), DM send $0.015, list create $0.010, engagement writes\ncurrently $0. X also caps post reads at **2,000,000 per month**. The authoritative table is\n[`docs/01-api-landscape.md`](docs/01-api-landscape.md) §3; the operator's view is\n[`docs/10-operator-guide.md`](docs/10-operator-guide.md) §5.\n\nThe budget is per process, advisory, resets on restart, and is **model-immutable** — there\nis no per-call override and no tool that raises it.\n\n## Run / debug\n\nMCP clients spawn the server for you. To run it by hand:\n\n```bash\nX_MCP_POLICY=read-only node build/src/index.js serve\n```\n\n### Command-line interface\n\n| Command | What it does |\n|---|---|\n| `serve` *(default)* | Start the MCP server over stdio. Running with no subcommand also serves. |\n| `authorize [--manual] [--port <port>]` | Run the one-time OAuth 2.0 PKCE authorization flow and persist the token file. |\n| `doctor [--connect]` | Print resolved config, path/permission checks and the policy matrix; no billable calls. `--connect` adds one unauthenticated reachability GET. |\n\nstdout carries JSON-RPC only; diagnostics, warnings and the single\n`x-mcp-ai: fatal: <reason>` startup line go to stderr. Symptom-driven fixes are in\n[`docs/11-troubleshooting.md`](docs/11-troubleshooting.md).\n\n## Develop\n\n```bash\ngit clone https://github.com/IvanBBaev/x-mcp.git\ncd x-mcp\nnpm ci\nnpm run build         # tsc → build/\nnpm run check         # typecheck + lint + format:check + test\n```\n\nOther scripts: `npm run typecheck`, `npm run lint`, `npm run format` / `format:check`,\n`npm test`, `npm run coverage` (c8), and `npm run verify` (clean build + coverage + lint +\nformat check). See [`CONTRIBUTING.md`](CONTRIBUTING.md) for conventions and the full quality\ngate.\n\n## Tools\n\nThe 41 tools registered today. \"Read-only\" marks tools in a `read:*` policy cell — those\ncallable under the default preset (DM reads excepted: they need an explicit allow).\n\"User\" marks `user-only` tools, which require OAuth 2.0 user context and are unreachable\nwith an app-only bearer token. The designed surface is\n[`docs/03-tool-catalog.md`](docs/03-tool-catalog.md); the full per-tool reference —\nschemas, scopes, cost class, availability — is\n[`docs/reference/tools.md`](docs/reference/tools.md).\n\n> The table below is **generated** from the tool registry by `npm run docs:gen`. Do not edit\n> it by hand: `npm run check` regenerates and diffs it, so an edit fails CI rather than\n> shipping. Same for `docs/reference/tools.md`.\n\n<!-- GENERATED:TOOLS:BEGIN -->\n\n| Package | Tool | Cell | Read-only | User | Description |\n|---|---|---|:--:|:--:|---|\n| auth | `x_auth_status` | read:account | ✅ |  | Report the active auth mode, the authenticated user (in user mode), granted OAuth scopes, the credential backend, detected availability, and the resolved policy matrix. |\n| auth | `x_rate_limit_status` | read:account | ✅ |  | Dump the in-process rate-limit table — per bucket (endpoint-class × auth-context), each tracked window's limit, remaining, reset time, and whether it is currently exhausted. |\n| posts | `x_post_get` | read:content | ✅ |  | Batch-fetch one or more X (Twitter) posts by numeric id or status URL (1-100 per call). |\n| posts | `x_post_create` | write:content |  | ✅ | Create a post — text, optional reply_to_id, quote_id, media_ids[], poll {options[], duration_minutes}, reply_settings. |\n| posts | `x_post_delete` | destructive:content |  | ✅ | Delete own post by id. |\n| posts | `x_post_hide_reply` | write:moderation |  | ✅ | Hide or unhide a reply to one of your own posts. |\n| users | `x_user_get` | read:user | ✅ |  | Batch fetch of X (Twitter) user profiles by numeric id, @handle, bare handle, or the sentinel `me` (the authenticated user). |\n| search | `x_search_recent` | read:content | ✅ |  | Search X (Twitter) posts from the last 7 days using the full v2 query syntax (from:, to:, conversation_id:, boolean operators). |\n| search | `x_post_counts_recent` | read:content | ✅ |  | Return a volume histogram (post counts per time bucket) for an X (Twitter) v2 query over the last 7 days, at minute/hour/day granularity. |\n| engagement | `x_like_set` | write:engagement |  | ✅ | Like or unlike a post as the authenticated user. |\n| engagement | `x_repost_set` | write:engagement |  | ✅ | Repost (retweet) a post as the authenticated user, or undo that repost. |\n| engagement | `x_bookmark_set` | write:engagement |  | ✅ | Add a post to the authenticated user's bookmarks or remove it. |\n| engagement | `x_bookmarks_list` | read:content | ✅ | ✅ | The authenticated user's own bookmarks, newest first — the read half of `x_bookmark_set`. |\n| timelines | `x_timeline_home` | read:content | ✅ | ✅ | Read the authenticated X (Twitter) user's home timeline in reverse-chronological order (the accounts they follow, newest first). |\n| timelines | `x_timeline_mentions` | read:content | ✅ |  | Read posts mentioning an X (Twitter) user (defaults to the authenticated user). |\n| timelines | `x_timeline_user` | read:content | ✅ |  | Read an X (Twitter) user's own posts, newest first, optionally excluding replies and/or reposts, within optional time bounds. |\n| graph | `x_follow_set` | write:social-graph |  | ✅ | Follow or unfollow a user as the authenticated user. |\n| graph | `x_mute_set` | write:social-graph |  | ✅ | Mute or unmute a user as the authenticated user. |\n| graph | `x_block_set` | destructive:social-graph |  | ✅ | Block or unblock a user as the authenticated user. |\n| graph | `x_followers_list` | read:social-graph | ✅ |  | List the accounts following an X (Twitter) user. |\n| graph | `x_following_list` | read:social-graph | ✅ |  | List the accounts an X (Twitter) user follows. |\n| graph | `x_user_search` | read:user | ✅ |  | Keyword search over X (Twitter) user profiles (names, handles, bios). |\n| lists | `x_list_create` | write:content |  | ✅ | Create a list owned by the authenticated user. |\n| lists | `x_list_update` | write:content |  | ✅ | Update the authenticated user's own list metadata — `name`, `description`, and/or `private`. |\n| lists | `x_list_delete` | destructive:content |  | ✅ | Permanently delete the authenticated user's own list. |\n| lists | `x_list_get` | read:content | ✅ |  | Read one list's metadata — name, description, privacy, member and follower counts, and owner handle. |\n| lists | `x_lists_owned` | read:content | ✅ |  | The lists a user owns (defaults to the authenticated user). |\n| lists | `x_list_member_set` | write:content |  | ✅ | Add a user to the authenticated user's own list or remove one — a single user per call. |\n| lists | `x_list_members` | read:content | ✅ |  | The members of a list. |\n| lists | `x_list_timeline` | read:content | ✅ |  | Posts from a list's timeline (recent posts by its members). |\n| lists | `x_list_follow_set` | write:engagement |  | ✅ | Follow a list as the authenticated user, or unfollow it. |\n| lists | `x_list_pin_set` | write:engagement |  | ✅ | Pin a list in the authenticated user's list view, or unpin it. |\n| media | `x_media_upload` | write:content |  | ✅ | Upload a local image, GIF, or video via the chunked v2 flow and return a `media_id` to attach with `x_post_create`. |\n| media | `x_media_status` | read:content | ✅ | ✅ | Check the async processing state of an uploaded media by `media_id`. |\n| dm | `x_dm_events_list` | read:dm | ✅ | ✅ | List all recent direct-message events across the authenticated X (Twitter) user's conversations, newest first. |\n| dm | `x_dm_conversation_events_list` | read:dm | ✅ | ✅ | List the direct-message events of one X (Twitter) DM conversation, newest first. |\n| dm | `x_dm_participant_events_list` | read:dm | ✅ | ✅ | List the direct-message events of the 1:1 X (Twitter) DM conversation with one participant, newest first. |\n| dm | `x_dm_send` | write:dm |  | ✅ | Send an X (Twitter) direct message to exactly one target: an existing conversation (conversation_id) or a user (participant), creating the 1:1 conversation if needed. |\n| archive | `x_search_archive` | read:content | ✅ |  | Search the complete X (Twitter) archive back to 2006 using the full v2 query syntax (from:, to:, conversation_id:, boolean operators). |\n| archive | `x_post_counts_archive` | read:content | ✅ |  | Return a volume histogram (post counts per time bucket) for an X (Twitter) v2 query over the complete archive back to 2006, at minute/hour/day granularity. |\n| usage | `x_usage_get` | read:account | ✅ |  | Report the post-read consumption of the current billing cycle against the monthly project cap (with an optional per-day and per-app breakdown), alongside the local credit-spend estimate for this session. |\n\n<!-- GENERATED:TOOLS:END -->\n\nDM reads return ids, timestamps and participants only; message bodies require an explicit\n`include_text: true` on the call.\n\n### Tool packages\n\n| Package | Covers |\n|---|---|\n| `auth` | Auth context and rate-limit windows. |\n| `usage` | Platform read-cap consumption and the local session-spend estimate. |\n| `posts` | Create, read and delete posts. |\n| `search` | Recent post search and volume counts. |\n| `archive` | Full-archive search and counts. |\n| `timelines` | Home, mentions and user timelines. |\n| `engagement` | Likes, reposts and bookmarks. |\n| `users` | User lookup. |\n| `graph` | Profile search, follow/mute/block, follower and following lists. |\n| `lists` | Full list lifecycle, membership, timeline, follow and pin. |\n| `media` | Chunked media upload and status. |\n| `dm` | Direct-message reads and sends (double-locked). |\n\n## Resources\n\nMCP resources are **planned** — a read-only exposure of the resolved auth context and live\nrate-limit table as addressable resources. Not shipped.\n\n## Prompts\n\nMCP prompts are **planned** — guided templates for common workflows (e.g. cost-aware\nposting, audience research). Not shipped.\n\n## Project structure\n\nPorts & adapters; the module layout is fixed in\n[`docs/02-architecture.md`](docs/02-architecture.md) §3:\n\n```\nsrc/\n├── index.ts            # composition root + stdio wiring\n├── core/               # config, policy, budget, errors, ports, tooldef,\n│                       #   registry, render, resolve, paginate, sanitize\n├── api/                # http, ratelimit, errors, oauth2/, endpoints/\n├── tools/              # one module per package (posts, search, graph, …)\n├── mcp/                # compose, server, schema, structured, gates, session\n└── cli/                # dispatch, authorize, doctor\n```\n\nDependency rule: `tools → core + api/endpoints`, `api → core`, `mcp → tools + core`,\n`cli → core + api`. Nothing in `core` reaches outward or does I/O.\n\n## Security notes\n\nA summary; the full threat model and operator checklist live in\n[`SECURITY.md`](SECURITY.md) and [`docs/04-security.md`](docs/04-security.md).\n\n- **Host-scoped auth.** The `Authorization` header is attached only for the configured API\n  origin; redirects are never followed on token-bearing requests (confused-deputy defense).\n  Proxy environment variables are ignored.\n- **Token file hardening.** Written `0600` with `O_NOFOLLOW`/`O_EXCL`; refresh is\n  single-flight with reload-under-lock and fails closed rather than racing.\n- **Untrusted content.** Post/user/DM text returned to the model is marked as untrusted.\n  Marking is not a semantic filter — the **policy model is the real control** against\n  prompt injection.\n- **No escalation recipes.** A denial on a sensitive cell (`*:dm`, `destructive:*`,\n  `*:social-graph`) names the blocked cell but never the variable that would unlock it, so\n  the model cannot relay an escalation recipe to you.\n- **Media default-deny.** Uploads are refused unless the file `realpath`s inside\n  `X_MCP_MEDIA_DIR`.\n- **Cost is model-immutable.** The session credit budget is operator-set; the model cannot\n  raise or disable it.\n- **Supply chain: pin the exact version.** An unpinned `npx -y x-mcp-ai` executes the\n  newest publish on every client cold-start — in a process holding your tokens. Releases\n  are published from CI with npm provenance. The npm package name is `x-mcp-ai`; `x-mcp`\n  is only the repository name.\n\n## Data handling\n\nFull statement: [`docs/12-privacy.md`](docs/12-privacy.md).\n\n- **Nothing phones home.** No telemetry, no analytics, no update check. The project runs no\n  server; the only outbound destination is the X API at your configured base URL.\n- **Credentials stay local.** Client id/secret and bearer tokens live in the process\n  environment; OAuth tokens live in a `0600` file on your machine. No tool ever returns a\n  credential, and `doctor` masks them.\n- **Cost telemetry is local-only.** The spend counter is in memory, per process, reported to\n  the calling model and nowhere else.\n- **Content you read leaves X for your model.** Posts, profiles and DM events fetched by a\n  tool are returned to your MCP client and therefore reach its model provider. Nothing is\n  cached or persisted by this server.\n\n## Documentation\n\n| Page | For |\n|---|---|\n| [10 — Operator guide](docs/10-operator-guide.md) | Install, authorize, per-client config, env recipes, cost control. |\n| [11 — Troubleshooting](docs/11-troubleshooting.md) | Startup errors, `doctor`, auth/refresh, rate limits, missing tools. |\n| [12 — Privacy & data handling](docs/12-privacy.md) | What is sent where, what is stored, how to delete it. |\n| [01 — API landscape](docs/01-api-landscape.md) | Pay-per-use pricing, availability classes, platform caps. |\n| [02 — Architecture](docs/02-architecture.md) | Module layout and the canonical env-var table. |\n| [03 — Tool catalog](docs/03-tool-catalog.md) | The designed tool surface and its classifications. |\n| [04 — Security](docs/04-security.md) | Threat model, policy model, token lifecycle. |\n\n## Support\n\nIf this project saves you time, support is welcome:\n\n[![Sponsor](https://img.shields.io/badge/GitHub-Sponsors-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/IvanBBaev)\n[![Ko-fi](https://img.shields.io/badge/Ko--fi-Buy%20me%20a%20coffee-ff5e5b?style=flat-square&logo=kofi)](https://ko-fi.com/ivanbbaev)\n[![Donatree](https://img.shields.io/badge/Donatree-Donate-22c55e?style=flat-square)](https://donatr.ee/ivanbbaev/)\n\n## Trademark\n\nx-mcp-ai is an independent, unofficial project. It is **not affiliated with, endorsed by, or\nsponsored by X Corp**. It talks to the official, publicly documented X API v2 and does not\nuse any private, undocumented or scraping-based access.\n\n\"X\", \"Twitter\", and related names, logos and marks are trademarks of X Corp. They are used\nhere **nominatively**, only to describe what this software interoperates with. This project\nis released under the [MIT License](LICENSE); trademark rights are not licensed.\n",
  "bytes": 25884,
  "sha": "39c0951a2841fd00f4cfd06922539ddbc817f834e6b9819c5edd2dd1bfaf7eac",
  "repo_slug": "ivanbbaev/x-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_ivanbbaev_x_mcp_ai_dcc5372d/readme"
}