x-relay-mcp 1.1.0 → 1.2.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/.claude/skills/x-relay/SKILL.md +27 -1
- package/dist/{cli-DO7p1WNQ.d.ts → cli-B4ohNfa7.d.ts} +61 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +627 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +32 -3
- package/dist/index.js +639 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-shim.js +677 -2
- package/dist/mcp-shim.js.map +1 -1
- package/package.json +1 -1
|
@@ -100,7 +100,33 @@ xrelay sync bookmarks|posts|all [--handle <you>] [--repair] [--max N]
|
|
|
100
100
|
```
|
|
101
101
|
- Pulls ONLY tweets newer than the last sync (snowflake-id watermark + newest-first early-break) — never a
|
|
102
102
|
full refetch. `--repair` refetches everything and patches records; `--max N` caps a run (good for a first
|
|
103
|
-
sync). `posts`
|
|
103
|
+
sync). `posts` auto-detects your handle from the session (override/remember with `--handle`). Returns
|
|
104
|
+
`{ source, added, total, watermark }`.
|
|
105
|
+
|
|
106
|
+
### More endpoints
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
xrelay list <list-id> [--limit N] # tweets from a Twitter List (curated sources)
|
|
110
|
+
xrelay user-media <handle> [--limit N] # a user's images/videos only (visual evidence)
|
|
111
|
+
xrelay followers <handle> [--limit N] # a user's followers (network mapping)
|
|
112
|
+
xrelay following <handle> [--limit N] # who a user follows
|
|
113
|
+
xrelay retweeters <id|url> [--limit N] # who retweeted a tweet (amplification graph)
|
|
114
|
+
xrelay likers <id|url> [--limit N] # who liked a tweet (engagement graph)
|
|
115
|
+
xrelay quoters <id|url> [--limit N] # tweets quoting a tweet (reactions; recency-windowed)
|
|
116
|
+
xrelay trends [--woeid N] [--limit N] # what's hot now (woeid 1 = worldwide, default)
|
|
117
|
+
xrelay article <id|url> # a long-form X Article → Markdown
|
|
118
|
+
xrelay media <id|url> [--out <dir>] # a tweet's image/video URLs; --out downloads the files
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- **`retweeters`/`followers`/`following`** return `{ users:[<profile>...], nextCursor }` — the
|
|
122
|
+
amplification/audience graph. Use them to answer "who is paying attention to / amplifying X".
|
|
123
|
+
- **`likers`** also returns `{ users }`, but X made likes private in 2024, so it's usually **empty** for
|
|
124
|
+
tweets you don't own (only the like *count* is public — read that from the tweet's `metrics.likes`).
|
|
125
|
+
- **`quoters`** is search-based (`quoted_tweet_id:`), so it's recency-windowed, not the full historical set.
|
|
126
|
+
- **`trends`** is a cheap zoomed-out entry point before drilling into `search`.
|
|
127
|
+
- **`article`** returns `{ id, title, markdown, url }` — the full long-form read for a finalist.
|
|
128
|
+
- **`media`** returns `{ tweetId, media:[{type,url,...}], files? }`; `--out <dir>` saves the actual
|
|
129
|
+
image/video files (for OCR / transcription / multimodal analysis).
|
|
104
130
|
|
|
105
131
|
---
|
|
106
132
|
|
|
@@ -84,6 +84,37 @@ type ThreadResult = {
|
|
|
84
84
|
nextCursor?: string;
|
|
85
85
|
};
|
|
86
86
|
type SearchProduct$1 = 'Top' | 'Latest' | 'Media' | 'People';
|
|
87
|
+
/** A paginated set of users (followers / following / retweeters / likers). */
|
|
88
|
+
type UserPage = {
|
|
89
|
+
users: UserProfile[];
|
|
90
|
+
nextCursor?: string;
|
|
91
|
+
};
|
|
92
|
+
/** A trending topic. */
|
|
93
|
+
type Trend = {
|
|
94
|
+
name: string;
|
|
95
|
+
rank?: number;
|
|
96
|
+
/** Volume blurb as X reports it, e.g. "42.1K posts". */
|
|
97
|
+
volume?: string;
|
|
98
|
+
url?: string;
|
|
99
|
+
};
|
|
100
|
+
/** A downloadable media asset attached to a tweet. */
|
|
101
|
+
type MediaItem = {
|
|
102
|
+
type: MediaKind;
|
|
103
|
+
url: string;
|
|
104
|
+
thumbnail?: string;
|
|
105
|
+
width?: number;
|
|
106
|
+
height?: number;
|
|
107
|
+
durationMs?: number;
|
|
108
|
+
bitrate?: number;
|
|
109
|
+
};
|
|
110
|
+
/** A long-form X Article rendered to Markdown. */
|
|
111
|
+
type Article = {
|
|
112
|
+
id: string;
|
|
113
|
+
title: string;
|
|
114
|
+
markdown: string;
|
|
115
|
+
url: string;
|
|
116
|
+
author?: Author;
|
|
117
|
+
};
|
|
87
118
|
|
|
88
119
|
/** The two load-bearing cookies, plus any others the jar carries. */
|
|
89
120
|
type Cookies = {
|
|
@@ -150,6 +181,22 @@ declare const OPS: {
|
|
|
150
181
|
readonly queryId: "7UuJsFvnWuZo0HmxrzU42Q";
|
|
151
182
|
readonly operationName: "ListLatestTweetsTimeline";
|
|
152
183
|
};
|
|
184
|
+
readonly Retweeters: {
|
|
185
|
+
readonly queryId: "TZsWuSj7vGmncVnq7KWDUQ";
|
|
186
|
+
readonly operationName: "Retweeters";
|
|
187
|
+
};
|
|
188
|
+
readonly Favoriters: {
|
|
189
|
+
readonly queryId: "LLkw5EcVutJL6y-2gkz22A";
|
|
190
|
+
readonly operationName: "Favoriters";
|
|
191
|
+
};
|
|
192
|
+
readonly GenericTimelineById: {
|
|
193
|
+
readonly queryId: "_dGVIf1cY6xFanFNPsAzPQ";
|
|
194
|
+
readonly operationName: "GenericTimelineById";
|
|
195
|
+
};
|
|
196
|
+
readonly TweetResultByRestId: {
|
|
197
|
+
readonly queryId: "Xl5pC_lBk_gcO2ItU39DQw";
|
|
198
|
+
readonly operationName: "TweetResultByRestId";
|
|
199
|
+
};
|
|
153
200
|
};
|
|
154
201
|
type OpName = keyof typeof OPS;
|
|
155
202
|
type Vars = Record<string, unknown>;
|
|
@@ -204,8 +251,21 @@ interface Engine {
|
|
|
204
251
|
search(query: string, opts?: SearchOpts): Promise<SearchResult>;
|
|
205
252
|
user(handle: string): Promise<UserProfile | null>;
|
|
206
253
|
userTweets(handle: string, opts?: UserTweetsOpts): Promise<TweetPage>;
|
|
254
|
+
userMedia(handle: string, opts?: PageOpts): Promise<TweetPage>;
|
|
207
255
|
bookmarks(opts?: PageOpts): Promise<TweetPage>;
|
|
208
256
|
thread(id: string): Promise<ThreadResult>;
|
|
257
|
+
list(listId: string, opts?: PageOpts): Promise<TweetPage>;
|
|
258
|
+
followers(handle: string, opts?: PageOpts): Promise<UserPage>;
|
|
259
|
+
following(handle: string, opts?: PageOpts): Promise<UserPage>;
|
|
260
|
+
retweeters(tweetId: string, opts?: PageOpts): Promise<UserPage>;
|
|
261
|
+
likers(tweetId: string, opts?: PageOpts): Promise<UserPage>;
|
|
262
|
+
quoters(tweetId: string, opts?: SearchOpts): Promise<SearchResult>;
|
|
263
|
+
trends(opts?: {
|
|
264
|
+
woeid?: number;
|
|
265
|
+
limit?: number;
|
|
266
|
+
}): Promise<Trend[]>;
|
|
267
|
+
article(tweetId: string): Promise<Article | null>;
|
|
268
|
+
media(tweetId: string): Promise<MediaItem[]>;
|
|
209
269
|
/** The authenticated user's own @handle (from the session), or null. Memoized. */
|
|
210
270
|
me(): Promise<string | null>;
|
|
211
271
|
}
|
|
@@ -233,4 +293,4 @@ declare function parseArgs(argv: string[]): ParsedArgs;
|
|
|
233
293
|
declare function dispatch(parsed: ParsedArgs, engine: Engine): Promise<Envelope<unknown>>;
|
|
234
294
|
declare function run(argv: string[], engine?: Engine): Promise<number>;
|
|
235
295
|
|
|
236
|
-
export { type
|
|
296
|
+
export { type Article as A, type Cookies as C, type Err as E, type MediaItem as M, type Ok as O, type PageOpts as P, type SearchResult as S, type Tweet as T, type UserPage as U, type Engine as a, type Envelope as b, type TweetPage as c, type SearchProduct as d, type ThreadResult as e, type Trend as f, type UserProfile as g, type Author as h, type EngineDeps as i, EngineError as j, type MediaKind as k, type Metrics as l, type SearchOpts as m, type SearchProduct$1 as n, type UserTweetsOpts as o, createEngine as p, dispatch as q, parseArgs as r, parseCookies as s, run as t, type ParsedArgs as u };
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export {
|
|
2
|
+
export { u as ParsedArgs, q as dispatch, r as parseArgs, t as run } from './cli-B4ohNfa7.js';
|