From 6a39659599414e7fccec40f7c8e236c9e40d4666 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 13 Aug 2026 21:55:28 +0000 Subject: [PATCH] Switch X plugin to OAuth user sign-in with write scopes Co-authored-by: Alex Vandak Maloney --- third_party/x/.cursor-plugin/plugin.json | 19 ++----- third_party/x/CHANGELOG.md | 7 +++ third_party/x/README.md | 63 +++++++++++------------- third_party/x/mcp.json | 20 +++++++- 4 files changed, 59 insertions(+), 50 deletions(-) diff --git a/third_party/x/.cursor-plugin/plugin.json b/third_party/x/.cursor-plugin/plugin.json index fa57036..2422b3e 100644 --- a/third_party/x/.cursor-plugin/plugin.json +++ b/third_party/x/.cursor-plugin/plugin.json @@ -1,11 +1,11 @@ { "name": "x", "displayName": "X", - "version": "1.0.0", + "version": "2.0.0", "minClientVersions": { "cursor": "3.13.0" }, - "description": "Read-only access to the X API — search posts and users, read timelines and mentions, and pull trends and news — via X's official hosted MCP server.", + "description": "Connect to the X API — search posts and users, read timelines and mentions, pull trends and news, and manage lists, bookmarks, blocks, and mutes — via X's official hosted MCP server.", "author": { "name": "Cursor", "email": "plugins@cursor.com" @@ -21,6 +21,8 @@ "search", "trends", "news", + "lists", + "bookmarks", "social", "mcp" ], @@ -31,18 +33,5 @@ "search", "mcp" ], - "variables": { - "type": "object", - "properties": { - "X_BEARER_TOKEN": { - "type": "string", - "title": "X app-only Bearer token", - "description": "App-only Bearer token from your app's Keys and tokens page in the X Developer Portal (https://developer.x.com). Grants read-only access to the X API with no user context." - } - }, - "required": [ - "X_BEARER_TOKEN" - ] - }, "mcpServers": "./mcp.json" } diff --git a/third_party/x/CHANGELOG.md b/third_party/x/CHANGELOG.md index 08af2f4..ea41e22 100644 --- a/third_party/x/CHANGELOG.md +++ b/third_party/x/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this plugin will be documented here. +## 2.0.0 — OAuth user sign-in, no longer read-only + +- Replaced the `X_BEARER_TOKEN` app-only route with OAuth user sign-in using X's client ID `NGdZYmo4VVp2T1BnRG55NlExOGQ6MTpjaQ`. +- Requested scopes: `tweet.read`, `users.read`, `follows.read`, `space.read`, `mute.read`, `like.read`, `list.read`, `list.write`, `block.read`, `block.write`, `bookmark.read`, `bookmark.write`, `billing.write`, `offline.access`. +- Agents can now manage lists, bookmarks, blocks, and mutes in your user context. Posting is still not possible (`tweet.write` is not requested). +- Removed the `X_BEARER_TOKEN` plugin variable — no credential to paste anymore. + ## 1.0.0 — initial release - Logo: X's official mark from the X brand toolkit, on a black tile matching X's own app icon. diff --git a/third_party/x/README.md b/third_party/x/README.md index 3af825c..7d130c5 100644 --- a/third_party/x/README.md +++ b/third_party/x/README.md @@ -2,13 +2,13 @@ Cursor plugin that connects agents to the [X API](https://docs.x.com) through X's official hosted [Model Context Protocol](https://modelcontextprotocol.io/) server at `https://api.x.com/mcp`. -This plugin uses X's **app-only Bearer** route, which is read-only: agents can search and read public X data, but cannot post, bookmark, publish Articles, or act as any user. +This plugin signs you in with OAuth as your own X account. It is no longer read-only: alongside searching and reading public X data, agents can manage your lists, bookmarks, blocks, and mutes. ## Install 1. Open **Cursor Settings → Plugins**. 2. Search for **X**. -3. Click **Install**, then set your app-only Bearer token (below). +3. Click **Install**, then complete the OAuth sign-in when prompted. Or run `/add-plugin x` in chat. @@ -20,8 +20,24 @@ Or run `/add-plugin x` in chat. "x": { "type": "http", "url": "https://api.x.com/mcp", - "headers": { - "Authorization": "Bearer ${X_BEARER_TOKEN}" + "auth": { + "CLIENT_ID": "NGdZYmo4VVp2T1BnRG55NlExOGQ6MTpjaQ", + "scopes": [ + "tweet.read", + "users.read", + "follows.read", + "space.read", + "mute.read", + "like.read", + "list.read", + "list.write", + "block.read", + "block.write", + "bookmark.read", + "bookmark.write", + "billing.write", + "offline.access" + ] } } } @@ -30,47 +46,28 @@ Or run `/add-plugin x` in chat. ## What agents can do -| Category | Read-only capabilities | +| Category | Capabilities | | --- | --- | | Posts | Fetch posts, see likers / reposters / quoters, recent counts | | Search | Full-archive post search, user search, news search | | Users | Look up users by id or handle; read a user's posts, timeline, and mentions | | News & trends | Get news stories, get trends for a location (WOEID) | +| Follows, likes & Spaces | Read your follows, likes, and Spaces | +| Lists | Read and manage your lists | +| Bookmarks | Read and manage your bookmarks | +| Blocks & mutes | Read your blocks and mutes; add or remove blocks | -Write tools and user-context tools (bookmarks, Articles, resolving the current user) are not reachable with an app-only token. See [Full user-context access](#full-user-context-access) if you need them. +Posting is not included: the plugin does not request the `tweet.write` scope, so agents cannot publish posts as you. ## Setup -No credential ships with this plugin — it carries only a `${X_BEARER_TOKEN}` placeholder, and each install supplies its own token. +No token to paste — the plugin ships with X's OAuth client ID and requests the scopes above. On first use, Cursor opens a browser window where you sign in to X and approve access. The `offline.access` scope lets Cursor refresh the session automatically, so you only sign in once. -1. Create an app in the [X Developer Portal](https://developer.x.com). -2. Open the app's **Keys and tokens** page and copy the **Bearer Token** (the app-only token). -3. In **Dashboard → Plugins → Configure**, set **X app-only Bearer token** to that value. +Requests run in your user context, so they count against your account's rate limits. You can revoke access at any time from your X account's connected apps settings. -The token carries your app's own quota and rate limits rather than a user's. Rotate or regenerate it from the developer portal if it is ever exposed. +## Scopes requested -On a team marketplace an admin sets the token once for everyone, so every member's tool calls share that app's rate limits. - -## Full user-context access - -X's other route runs the open-source [`xurl`](https://github.com/xdevplatform/xurl) bridge locally over stdio. It performs an OAuth 2.0 PKCE browser login, refreshes tokens automatically, and unlocks writes and user-context tools: - -```json -{ - "mcpServers": { - "x": { - "command": "npx", - "args": ["-y", "@xdevplatform/xurl", "mcp", "https://api.x.com/mcp"], - "env": { - "CLIENT_ID": "YOUR_X_APP_CLIENT_ID", - "CLIENT_SECRET": "YOUR_X_APP_CLIENT_SECRET" - } - } - } -} -``` - -That route needs OAuth 2.0 enabled on the app, `http://localhost:8080/callback` registered as a redirect URI, Node.js for `npx`, and a reachable browser for the first login — so it is deliberately not what this plugin ships. +`tweet.read`, `users.read`, `follows.read`, `space.read`, `mute.read`, `like.read`, `list.read`, `list.write`, `block.read`, `block.write`, `bookmark.read`, `bookmark.write`, `billing.write`, `offline.access` ## X documentation search diff --git a/third_party/x/mcp.json b/third_party/x/mcp.json index 6865c80..80f12c7 100644 --- a/third_party/x/mcp.json +++ b/third_party/x/mcp.json @@ -3,8 +3,24 @@ "x": { "type": "http", "url": "https://api.x.com/mcp", - "headers": { - "Authorization": "Bearer ${X_BEARER_TOKEN}" + "auth": { + "CLIENT_ID": "NGdZYmo4VVp2T1BnRG55NlExOGQ6MTpjaQ", + "scopes": [ + "tweet.read", + "users.read", + "follows.read", + "space.read", + "mute.read", + "like.read", + "list.read", + "list.write", + "block.read", + "block.write", + "bookmark.read", + "bookmark.write", + "billing.write", + "offline.access" + ] } } }