@twitterapis/mcp 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +22 -4
- package/package.json +5 -3
- package/src/tools.js +33 -24
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0 (2026-07-20)
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Removed three phantom parameters from the published tool schemas.** Eleven write tools (`twitter_create_tweet`, `twitter_delete_tweet`, `twitter_favorite_tweet` / `twitter_unfavorite_tweet`, `twitter_retweet` / `twitter_unretweet`, `twitter_bookmark_tweet` / `twitter_unbookmark_tweet`, `twitter_follow_user` / `twitter_unfollow_user`, `twitter_dm_send`) advertised an optional `account` parameter that the API never accepted, so agents that passed it were silently ignored. `twitter_tweet_replies` and `twitter_tweet_retweeters` advertised the full pagination shape when the endpoint only accepts `cursor`.
|
|
8
|
+
- A fail-closed MCP-to-OpenAPI parity gate now runs on every `npm test`, so a tool schema can no longer drift from the live API contract unnoticed.
|
|
9
|
+
- README: corrected the Links section (the REST base URL is `https://api.twitterapis.com`; removed a link to a status page that does not exist) and added an FAQ covering signup, read-vs-write scope, supported clients, billing, and data handling.
|
|
10
|
+
|
|
11
|
+
### Breaking
|
|
12
|
+
|
|
13
|
+
- If your client explicitly passed `account` to a write tool, or `count` to `twitter_tweet_replies` / `twitter_tweet_retweeters`, those keys are no longer part of the schema. They were never honoured by the API, so behaviour is unchanged; only the advertised schema is now accurate.
|
|
14
|
+
|
|
15
|
+
## 0.5.0 (2026-07-06)
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `twitter_user_followers_v2` and `twitter_user_following_v2` — the v2 response shape (richer profile fields and more reliable cursoring for large follower/following audiences). Same inputs as the v1 tools (`username` / `user_id` + `cursor`). Catalog is now **40 tools** (29 reads + 11 write actions).
|
|
20
|
+
|
|
21
|
+
### No breaking changes
|
|
22
|
+
|
|
3
23
|
## 0.3.0 (2026-06-29)
|
|
4
24
|
|
|
5
25
|
### Added
|
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @twitterapis/mcp
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@twitterapis/mcp)
|
|
4
|
+
[](https://www.npmjs.com/package/@twitterapis/mcp)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
3
7
|
Official **Model Context Protocol** server for [twitterapis.com](https://www.twitterapis.com), the Twitter / X API as native tools for Claude, Cursor, Windsurf, and any MCP client. Reads (search, profiles, timelines, followers, DMs) plus write actions (post, like, retweet, follow).
|
|
4
8
|
|
|
5
9
|
Ask your agent to search tweets, pull a user's profile or timeline, list followers/following, fetch thread context, or enumerate list members and it calls the API directly. Every tool maps to a REST endpoint at `https://api.twitterapis.com`; the server holds no state and forwards your API key on each call.
|
|
@@ -87,7 +91,7 @@ Restart Claude Desktop. The `twitter_*` tools appear in the tool picker.
|
|
|
87
91
|
|
|
88
92
|
## Tools
|
|
89
93
|
|
|
90
|
-
|
|
94
|
+
40 tools: 29 reads and 11 write actions. Most user endpoints accept `username` (handle without @) **or** `user_id` (`twitter_user_likes` and `twitter_user_tweets_complete` require `user_id`); tweet endpoints accept `id` **or** `url`; paginated endpoints return a `cursor` you pass back to get the next page.
|
|
91
95
|
|
|
92
96
|
Public reads (search, profiles, tweets, followers, likes) work with just your API key. The **account-only** reads (bookmarks, DMs, home timeline, followers-you-know) and **all write actions** act AS an authenticated X account, so they need a session linked to your key first (returns HTTP 409 until then). Alternatively, pass **per-call inline credentials** on any of those tools (`auth_token` + `ct0`, with optional `proxy_url` / `user_agent`) to act AS that account for a single call without pre-registering a session, so one API key can act as many accounts. For write actions, set `proxy_url` to a residential proxy, since X soft-blocks writes that egress from datacenter IPs. Each write tool is annotated `readOnlyHint: false`; reversing actions (delete, unfollow, unlike, unretweet, unbookmark) are annotated `destructiveHint: true` so MCP clients can prompt before running them.
|
|
93
97
|
|
|
@@ -110,6 +114,8 @@ Public reads (search, profiles, tweets, followers, likes) work with just your AP
|
|
|
110
114
|
| `twitter_user_likes` | Tweets a user has liked (public Likes tab) |
|
|
111
115
|
| `twitter_user_followers` | Accounts that follow a user |
|
|
112
116
|
| `twitter_user_following` | Accounts a user follows |
|
|
117
|
+
| `twitter_user_followers_v2` | Followers with the v2 response shape (richer fields, deeper cursoring) |
|
|
118
|
+
| `twitter_user_following_v2` | Following with the v2 response shape (richer fields, deeper cursoring) |
|
|
113
119
|
| `twitter_user_verified_followers` | A user's verified followers only |
|
|
114
120
|
| `twitter_followers_you_know` | Followers of a target that your authenticated account also follows |
|
|
115
121
|
| `twitter_tweet_detail` | Single tweet: text, author, metrics, media, quoted/reply context |
|
|
@@ -202,14 +208,26 @@ count: 50
|
|
|
202
208
|
|
|
203
209
|
## Pricing
|
|
204
210
|
|
|
205
|
-
Calls are billed to your twitterapis.com account
|
|
211
|
+
Calls are billed to your twitterapis.com account. Almost every endpoint is $0.0008/call: all reads (search, profiles, tweets, followers, likes) plus the simple write actions (like, retweet, bookmark, follow and their undos, delete). At the read rate that works out to $0.04 per 1,000 tweets, since each call returns about 20 tweets. The premium endpoints cost a little more: tweet creation, sending a DM (`twitter_dm_send`), and DM reads (`twitter_dm_list`, `twitter_dm_conversation`) at $0.0016/call, full tweet history (`twitter_user_tweets_complete`) at $0.0024/call, and a full tweet thread (`twitter_tweet_thread`) at $0.004/call. Your first $0.50 is free. See [twitterapis.com/pricing](https://www.twitterapis.com/pricing).
|
|
206
212
|
|
|
207
213
|
## Links
|
|
208
214
|
|
|
209
215
|
- Docs: [docs.twitterapis.com](https://docs.twitterapis.com)
|
|
210
216
|
- Dashboard / API keys: [twitterapis.com/dashboard](https://www.twitterapis.com/dashboard)
|
|
211
|
-
-
|
|
212
|
-
-
|
|
217
|
+
- Pricing: [twitterapis.com/pricing](https://www.twitterapis.com/pricing)
|
|
218
|
+
- REST API base URL (call it directly, without MCP): `https://api.twitterapis.com`
|
|
219
|
+
|
|
220
|
+
## FAQ
|
|
221
|
+
|
|
222
|
+
**Do I need an X (Twitter) developer account?** No. Get an API key at [twitterapis.com/signup](https://www.twitterapis.com/signup); there is no application or approval step.
|
|
223
|
+
|
|
224
|
+
**Is it read-only?** No. 29 read tools work with just your API key; 11 write actions (post, like, retweet, follow, DM) act as a linked X account or per-call inline credentials.
|
|
225
|
+
|
|
226
|
+
**Which clients are supported?** Claude Desktop, Cursor, Windsurf, and VS Code (Copilot agent mode), or any Model Context Protocol client.
|
|
227
|
+
|
|
228
|
+
**How is it billed?** Per request. New keys start with $0.50 in free credits, no card required. See [pricing](https://www.twitterapis.com/pricing).
|
|
229
|
+
|
|
230
|
+
**Does it store my key or data?** No. The server holds no state and forwards your API key on each call.
|
|
213
231
|
|
|
214
232
|
## License
|
|
215
233
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twitterapis/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Official MCP server for twitterapis.com, the Twitter/X API (search, users, followers, tweets, threads, lists, likes, bookmarks, DMs) plus write actions (post/like/retweet/follow) as native tools for Claude, Cursor, and any MCP client.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "https://github.com/TwitterAPIs/twitterapis-mcp.git"
|
|
7
|
+
"url": "git+https://github.com/TwitterAPIs/twitterapis-mcp.git"
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"bin": {
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"scripts": {
|
|
24
24
|
"start": "node src/index.js",
|
|
25
25
|
"check": "node --check src/index.js && node --check src/tools.js",
|
|
26
|
-
"test": "node test/tools.test.mjs && node test/smoke.mjs"
|
|
26
|
+
"test": "node test/tools.test.mjs && node test/smoke.mjs && node test/openapi-parity.mjs && node test/firewall.mjs",
|
|
27
|
+
"check:openapi-parity": "node test/openapi-parity.mjs",
|
|
28
|
+
"check:firewall": "node test/firewall.mjs"
|
|
27
29
|
},
|
|
28
30
|
"dependencies": {
|
|
29
31
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
package/src/tools.js
CHANGED
|
@@ -10,13 +10,16 @@
|
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
|
|
12
12
|
// ── Shared Zod input-schema fragments ───────────────────────────────────────
|
|
13
|
+
const CURSOR = {
|
|
14
|
+
cursor: z.string().optional().describe(
|
|
15
|
+
"Opaque pagination cursor from a previous response's next_cursor field. Omit on the first call; pass on subsequent calls to fetch the next page.",
|
|
16
|
+
),
|
|
17
|
+
};
|
|
13
18
|
const PAGINATION = {
|
|
14
19
|
count: z.number().int().min(1).max(200).optional().describe(
|
|
15
20
|
"Max items to return for this page. Typical range 1 to 200; endpoint default (20) applies if omitted. To page through results, pass the cursor from the previous response.",
|
|
16
21
|
),
|
|
17
|
-
|
|
18
|
-
"Opaque pagination cursor from a previous response's next_cursor field. Omit on the first call; pass on subsequent calls to fetch the next page.",
|
|
19
|
-
),
|
|
22
|
+
...CURSOR,
|
|
20
23
|
};
|
|
21
24
|
const USER_REF = {
|
|
22
25
|
username: z.string().optional().describe(
|
|
@@ -34,14 +37,6 @@ const TWEET_REF = {
|
|
|
34
37
|
'Full tweet URL, e.g. "https://x.com/elonmusk/status/1789012345678901234". Provide exactly one of id or url.',
|
|
35
38
|
),
|
|
36
39
|
};
|
|
37
|
-
// Optional pooled-session selector, shared by every write action. A customer
|
|
38
|
-
// key maps to a default authenticated session; pass account only to target a
|
|
39
|
-
// specific handle in a multi-account pool.
|
|
40
|
-
const ACCOUNT = {
|
|
41
|
-
account: z.string().optional().describe(
|
|
42
|
-
"Optional. The @handle (without @) of the authenticated account to act AS, when your key manages more than one session. Omit to use your key's default session.",
|
|
43
|
-
),
|
|
44
|
-
};
|
|
45
40
|
// Per-call inline credentials. Pass an account's own X session cookies to act AS
|
|
46
41
|
// that account for this one call, without pre-registering a session, so a single
|
|
47
42
|
// API key can act as many accounts (e.g. polling several inboxes or posting from
|
|
@@ -225,6 +220,20 @@ export const TOOLS = [
|
|
|
225
220
|
"List the accounts that a given user follows. Returns profile data for each account followed. Paginate with cursor. Useful for mapping a user's information sources, influencer networks, or competitor monitoring lists.",
|
|
226
221
|
shape: { ...USER_REF, ...PAGINATION },
|
|
227
222
|
},
|
|
223
|
+
{
|
|
224
|
+
name: "twitter_user_followers_v2",
|
|
225
|
+
path: "/twitter/user/followers_v2",
|
|
226
|
+
description:
|
|
227
|
+
"List a user's followers using the v2 response shape (richer profile fields and more reliable cursoring for large audiences). Same inputs as twitter_user_followers; prefer this when you need the fuller v2 payload or are paging deep follower lists.",
|
|
228
|
+
shape: { ...USER_REF, ...PAGINATION },
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
name: "twitter_user_following_v2",
|
|
232
|
+
path: "/twitter/user/following_v2",
|
|
233
|
+
description:
|
|
234
|
+
"List the accounts a user follows using the v2 response shape (richer profile fields and more reliable cursoring). Same inputs as twitter_user_following; prefer this when you need the fuller v2 payload or are paging deep following lists.",
|
|
235
|
+
shape: { ...USER_REF, ...PAGINATION },
|
|
236
|
+
},
|
|
228
237
|
{
|
|
229
238
|
name: "twitter_user_verified_followers",
|
|
230
239
|
path: "/twitter/user/verified_followers",
|
|
@@ -258,14 +267,14 @@ export const TOOLS = [
|
|
|
258
267
|
path: "/twitter/tweet/replies",
|
|
259
268
|
description:
|
|
260
269
|
"Get replies to a specific tweet. Returns each reply tweet with author, text, and metrics. Paginate with cursor to load more. Use this to read the conversation under a tweet, gauge sentiment, or find notable responses.",
|
|
261
|
-
shape: { ...TWEET_REF, ...
|
|
270
|
+
shape: { ...TWEET_REF, ...CURSOR },
|
|
262
271
|
},
|
|
263
272
|
{
|
|
264
273
|
name: "twitter_tweet_thread",
|
|
265
274
|
path: "/twitter/tweet/thread",
|
|
266
275
|
description:
|
|
267
276
|
"Get all tweets in a thread: the connected chain of tweets posted by the SAME author in sequence (a tweetstorm or numbered thread). Pass any tweet id/url from the thread and the API returns the full ordered sequence. Paginate with cursor for long threads. Does NOT return replies from other users, use twitter_tweet_replies for that.",
|
|
268
|
-
shape: { ...TWEET_REF, ...
|
|
277
|
+
shape: { ...TWEET_REF, ...CURSOR },
|
|
269
278
|
},
|
|
270
279
|
{
|
|
271
280
|
name: "twitter_tweet_retweeters",
|
|
@@ -347,7 +356,7 @@ export const TOOLS = [
|
|
|
347
356
|
text: z.string().min(1).describe(
|
|
348
357
|
"The Direct Message body text to send (non-empty).",
|
|
349
358
|
),
|
|
350
|
-
...
|
|
359
|
+
...INLINE,
|
|
351
360
|
},
|
|
352
361
|
},
|
|
353
362
|
|
|
@@ -372,7 +381,7 @@ export const TOOLS = [
|
|
|
372
381
|
media_ids: z.string().optional().describe(
|
|
373
382
|
"Optional. Comma-separated media id(s) from a prior media upload to attach (images/video).",
|
|
374
383
|
),
|
|
375
|
-
...
|
|
384
|
+
...INLINE,
|
|
376
385
|
},
|
|
377
386
|
},
|
|
378
387
|
{
|
|
@@ -383,7 +392,7 @@ export const TOOLS = [
|
|
|
383
392
|
destructive: true,
|
|
384
393
|
description:
|
|
385
394
|
"Delete a tweet AS your authenticated account. Irreversible: the tweet is permanently removed. You can only delete tweets your authenticated account authored. Provide the tweet id or url. Requires write capability behind your key.",
|
|
386
|
-
shape: { ...TWEET_REF, ...
|
|
395
|
+
shape: { ...TWEET_REF, ...INLINE },
|
|
387
396
|
},
|
|
388
397
|
// ── Writes: engagement (favorite / retweet / bookmark) + inverses ──────────
|
|
389
398
|
{
|
|
@@ -393,7 +402,7 @@ export const TOOLS = [
|
|
|
393
402
|
write: true,
|
|
394
403
|
description:
|
|
395
404
|
"Like (favorite) a tweet AS your authenticated account. Provide the tweet id or url. Requires write capability behind your key. Reverse with twitter_unfavorite_tweet.",
|
|
396
|
-
shape: { ...TWEET_REF, ...
|
|
405
|
+
shape: { ...TWEET_REF, ...INLINE },
|
|
397
406
|
},
|
|
398
407
|
{
|
|
399
408
|
name: "twitter_unfavorite_tweet",
|
|
@@ -403,7 +412,7 @@ export const TOOLS = [
|
|
|
403
412
|
destructive: true,
|
|
404
413
|
description:
|
|
405
414
|
"Remove a like (unfavorite) from a tweet AS your authenticated account. Provide the tweet id or url. Requires write capability behind your key.",
|
|
406
|
-
shape: { ...TWEET_REF, ...
|
|
415
|
+
shape: { ...TWEET_REF, ...INLINE },
|
|
407
416
|
},
|
|
408
417
|
{
|
|
409
418
|
name: "twitter_retweet",
|
|
@@ -412,7 +421,7 @@ export const TOOLS = [
|
|
|
412
421
|
write: true,
|
|
413
422
|
description:
|
|
414
423
|
"Retweet a tweet AS your authenticated account. Provide the tweet id or url. Requires write capability behind your key. Reverse with twitter_unretweet.",
|
|
415
|
-
shape: { ...TWEET_REF, ...
|
|
424
|
+
shape: { ...TWEET_REF, ...INLINE },
|
|
416
425
|
},
|
|
417
426
|
{
|
|
418
427
|
name: "twitter_unretweet",
|
|
@@ -422,7 +431,7 @@ export const TOOLS = [
|
|
|
422
431
|
destructive: true,
|
|
423
432
|
description:
|
|
424
433
|
"Undo a retweet AS your authenticated account. Provide the tweet id or url. Requires write capability behind your key.",
|
|
425
|
-
shape: { ...TWEET_REF, ...
|
|
434
|
+
shape: { ...TWEET_REF, ...INLINE },
|
|
426
435
|
},
|
|
427
436
|
{
|
|
428
437
|
name: "twitter_bookmark_tweet",
|
|
@@ -431,7 +440,7 @@ export const TOOLS = [
|
|
|
431
440
|
write: true,
|
|
432
441
|
description:
|
|
433
442
|
"Bookmark a tweet to YOUR authenticated account's private bookmarks. Provide the tweet id or url. Requires write capability behind your key. Reverse with twitter_unbookmark_tweet.",
|
|
434
|
-
shape: { ...TWEET_REF, ...
|
|
443
|
+
shape: { ...TWEET_REF, ...INLINE },
|
|
435
444
|
},
|
|
436
445
|
{
|
|
437
446
|
name: "twitter_unbookmark_tweet",
|
|
@@ -441,7 +450,7 @@ export const TOOLS = [
|
|
|
441
450
|
destructive: true,
|
|
442
451
|
description:
|
|
443
452
|
"Remove a tweet from YOUR authenticated account's bookmarks. Provide the tweet id or url. Requires write capability behind your key.",
|
|
444
|
-
shape: { ...TWEET_REF, ...
|
|
453
|
+
shape: { ...TWEET_REF, ...INLINE },
|
|
445
454
|
},
|
|
446
455
|
// ── Writes: follow graph ───────────────────────────────────────────────────
|
|
447
456
|
{
|
|
@@ -455,7 +464,7 @@ export const TOOLS = [
|
|
|
455
464
|
user_id: z.string().describe(
|
|
456
465
|
"Numeric user id of the account to follow. Resolve a handle to a user_id first with twitter_user_info.",
|
|
457
466
|
),
|
|
458
|
-
...
|
|
467
|
+
...INLINE,
|
|
459
468
|
},
|
|
460
469
|
},
|
|
461
470
|
{
|
|
@@ -470,7 +479,7 @@ export const TOOLS = [
|
|
|
470
479
|
user_id: z.string().describe(
|
|
471
480
|
"Numeric user id of the account to unfollow.",
|
|
472
481
|
),
|
|
473
|
-
...
|
|
482
|
+
...INLINE,
|
|
474
483
|
},
|
|
475
484
|
},
|
|
476
485
|
];
|