@omnisocials/mcp-server 1.20.0 → 1.20.1
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/build/client.d.ts +94 -100
- package/build/client.js +21 -4
- package/build/tools/accounts.js +2 -2
- package/build/tools/analytics.js +15 -8
- package/build/tools/hashtag-sets.js +11 -1
- package/build/tools/inbox.js +4 -3
- package/build/tools/media.js +19 -3
- package/build/tools/posts.js +168 -202
- package/build/tools/webhooks.js +21 -1
- package/build/types.d.ts +295 -31
- package/package.json +1 -1
package/build/tools/webhooks.js
CHANGED
|
@@ -8,7 +8,7 @@ export function registerWebhookTools(server, getClient) {
|
|
|
8
8
|
content: [{ type: "text", text: `Error (${result.error.code}): ${result.error.message}` }],
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
-
const webhooks = Array.isArray(result.data) ? result.data :
|
|
11
|
+
const webhooks = Array.isArray(result.data) ? result.data : [];
|
|
12
12
|
if (!webhooks.length) {
|
|
13
13
|
return {
|
|
14
14
|
content: [{ type: "text", text: "No webhooks configured." }],
|
|
@@ -39,6 +39,11 @@ export function registerWebhookTools(server, getClient) {
|
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
const w = result.data;
|
|
42
|
+
if (!w) {
|
|
43
|
+
return {
|
|
44
|
+
content: [{ type: "text", text: "Webhook created, but the API returned no details. Verify with list_webhooks." }],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
42
47
|
let md = `## Webhook Created\n\n`;
|
|
43
48
|
md += `| Field | Value |\n`;
|
|
44
49
|
md += `|-------|-------|\n`;
|
|
@@ -64,6 +69,11 @@ export function registerWebhookTools(server, getClient) {
|
|
|
64
69
|
};
|
|
65
70
|
}
|
|
66
71
|
const w = result.data;
|
|
72
|
+
if (!w) {
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: "text", text: "Webhook not found." }],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
67
77
|
let md = `## Webhook Details\n\n`;
|
|
68
78
|
md += `| Field | Value |\n`;
|
|
69
79
|
md += `|-------|-------|\n`;
|
|
@@ -95,6 +105,11 @@ export function registerWebhookTools(server, getClient) {
|
|
|
95
105
|
};
|
|
96
106
|
}
|
|
97
107
|
const w = result.data;
|
|
108
|
+
if (!w) {
|
|
109
|
+
return {
|
|
110
|
+
content: [{ type: "text", text: "Webhook updated, but the API returned no details. Verify with list_webhooks." }],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
98
113
|
let md = `## Webhook Updated\n\n`;
|
|
99
114
|
md += `| Field | Value |\n`;
|
|
100
115
|
md += `|-------|-------|\n`;
|
|
@@ -124,6 +139,11 @@ export function registerWebhookTools(server, getClient) {
|
|
|
124
139
|
};
|
|
125
140
|
}
|
|
126
141
|
const w = result.data;
|
|
142
|
+
if (!w) {
|
|
143
|
+
return {
|
|
144
|
+
content: [{ type: "text", text: "Secret rotated, but the API returned no details." }],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
127
147
|
let md = `## Webhook Secret Rotated\n\n`;
|
|
128
148
|
md += `| Field | Value |\n`;
|
|
129
149
|
md += `|-------|-------|\n`;
|
package/build/types.d.ts
CHANGED
|
@@ -4,6 +4,14 @@ export interface ApiResponse<T = unknown> {
|
|
|
4
4
|
code: string;
|
|
5
5
|
message: string;
|
|
6
6
|
};
|
|
7
|
+
warnings?: Array<{
|
|
8
|
+
code: string;
|
|
9
|
+
message: string;
|
|
10
|
+
credits_required?: number;
|
|
11
|
+
credits_balance?: number | null;
|
|
12
|
+
enforced?: boolean;
|
|
13
|
+
enforce_from?: string;
|
|
14
|
+
}>;
|
|
7
15
|
pagination?: {
|
|
8
16
|
next_cursor: string | null;
|
|
9
17
|
has_more: boolean;
|
|
@@ -56,39 +64,183 @@ export interface InboxMessage {
|
|
|
56
64
|
thumbnail: string | null;
|
|
57
65
|
} | null;
|
|
58
66
|
}
|
|
59
|
-
|
|
67
|
+
/** One media entry on a post — a plain URL string, or an object carrying the
|
|
68
|
+
* url plus an optional accessibility description (alt text). */
|
|
69
|
+
export type ApiPostMediaEntry = string | {
|
|
70
|
+
id?: string | number;
|
|
71
|
+
url?: string;
|
|
72
|
+
alt?: string;
|
|
73
|
+
[k: string]: unknown;
|
|
74
|
+
};
|
|
75
|
+
/** A thread part as echoed back by the API (X / Bluesky / Mastodon). */
|
|
76
|
+
export interface ApiThreadPartOut {
|
|
77
|
+
id?: string;
|
|
78
|
+
text?: string;
|
|
79
|
+
media_urls?: Array<string | {
|
|
80
|
+
url?: string;
|
|
81
|
+
alt?: string;
|
|
82
|
+
}>;
|
|
83
|
+
[k: string]: unknown;
|
|
84
|
+
}
|
|
85
|
+
/** Per-platform option block echoed on a post. First comments (input +
|
|
86
|
+
* post-publish outcome), thread parts, and platform-specific settings all
|
|
87
|
+
* ride here under their platform key, mirroring the request shape. */
|
|
88
|
+
export interface ApiPlatformOptionsOut {
|
|
89
|
+
first_comment?: string;
|
|
90
|
+
first_comment_result?: {
|
|
91
|
+
status?: string;
|
|
92
|
+
error?: string;
|
|
93
|
+
[k: string]: unknown;
|
|
94
|
+
} | null;
|
|
95
|
+
thread_parts?: ApiThreadPartOut[];
|
|
96
|
+
[k: string]: unknown;
|
|
97
|
+
}
|
|
98
|
+
/** Instagram option block — adds the Reel-cover and Trial-Reel read-backs. */
|
|
99
|
+
export interface ApiInstagramOptionsOut extends ApiPlatformOptionsOut {
|
|
100
|
+
is_trial_reel?: boolean;
|
|
101
|
+
trial_graduation_strategy?: string;
|
|
102
|
+
thumbnail_type?: string;
|
|
103
|
+
thumb_offset?: number | string;
|
|
104
|
+
cover_url?: string;
|
|
105
|
+
}
|
|
106
|
+
export interface ApiPost {
|
|
60
107
|
id: string;
|
|
61
|
-
|
|
108
|
+
/** DB "posted" is mapped to "published" by the serializer. */
|
|
62
109
|
status: string;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
*
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
*/
|
|
110
|
+
/** "post" | "story" | "reel" */
|
|
111
|
+
type?: string;
|
|
112
|
+
/** Per-platform captions keyed by platform id plus "default". Legacy
|
|
113
|
+
* servers returned a plain string. */
|
|
114
|
+
content?: Record<string, string> | string;
|
|
115
|
+
/** Selected platforms — an array of platform ids on current servers;
|
|
116
|
+
* legacy servers returned a {platform: boolean} map. */
|
|
117
|
+
accounts?: string[] | Record<string, boolean>;
|
|
118
|
+
/** legacy servers (older key for `accounts`) */
|
|
119
|
+
channels?: string[] | Record<string, boolean>;
|
|
120
|
+
/** Flat array (same set everywhere) or per-platform map keyed
|
|
121
|
+
* "default"/platform. */
|
|
122
|
+
media?: ApiPostMediaEntry[] | Record<string, ApiPostMediaEntry[]>;
|
|
123
|
+
schedule_at?: string | null;
|
|
124
|
+
/** legacy servers */
|
|
125
|
+
scheduled_at?: string | null;
|
|
126
|
+
/** legacy servers */
|
|
127
|
+
published_at?: string | null;
|
|
128
|
+
approval_status?: string | null;
|
|
129
|
+
/** Deep link into the OmniSocials dashboard for this post. */
|
|
130
|
+
app_url?: string;
|
|
131
|
+
/** platform → live URL for each platform that successfully published. */
|
|
132
|
+
published_urls?: Record<string, string>;
|
|
133
|
+
/** Set on a retry post: the original failed post's id. */
|
|
134
|
+
retry_of?: string;
|
|
135
|
+
/** Set on the original post: ids of its retry posts. */
|
|
136
|
+
retries?: string[];
|
|
137
|
+
location_id?: string;
|
|
138
|
+
collaborators?: string[];
|
|
139
|
+
user_tags?: Array<string | {
|
|
140
|
+
username?: string;
|
|
141
|
+
x?: number;
|
|
142
|
+
y?: number;
|
|
143
|
+
image_index?: number;
|
|
144
|
+
}>;
|
|
145
|
+
link_url?: string;
|
|
146
|
+
link_title?: string;
|
|
147
|
+
link_description?: string;
|
|
148
|
+
link_thumbnail_url?: string;
|
|
149
|
+
youtube?: ApiPlatformOptionsOut;
|
|
150
|
+
pinterest?: ApiPlatformOptionsOut;
|
|
151
|
+
instagram?: ApiInstagramOptionsOut;
|
|
152
|
+
facebook?: ApiPlatformOptionsOut;
|
|
153
|
+
linkedin?: ApiPlatformOptionsOut;
|
|
154
|
+
linkedin_page?: ApiPlatformOptionsOut;
|
|
155
|
+
tiktok?: ApiPlatformOptionsOut;
|
|
156
|
+
google_business?: ApiPlatformOptionsOut;
|
|
157
|
+
x?: ApiPlatformOptionsOut;
|
|
158
|
+
bluesky?: ApiPlatformOptionsOut;
|
|
159
|
+
mastodon?: ApiPlatformOptionsOut;
|
|
160
|
+
/** platform → user-friendly error message; only failed platforms appear.
|
|
161
|
+
* null while draft/scheduled/processing or when every platform succeeded. */
|
|
75
162
|
errors?: Record<string, string> | null;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
163
|
+
source?: string | null;
|
|
164
|
+
created_at?: string;
|
|
165
|
+
updated_at?: string;
|
|
166
|
+
}
|
|
167
|
+
/** `data` of POST /posts/:id/publish — a small ack, not a full post
|
|
168
|
+
* (backend/routes/api/v1/posts.js publish route). */
|
|
169
|
+
export interface PublishPostResult {
|
|
170
|
+
id: string;
|
|
171
|
+
status: string;
|
|
172
|
+
message?: string;
|
|
173
|
+
}
|
|
174
|
+
/** `data` of POST /posts/:id/retry (backend/routes/api/v1/posts.js:4194). */
|
|
175
|
+
export interface RetryPostResult {
|
|
176
|
+
id: string;
|
|
177
|
+
status: string;
|
|
178
|
+
/** The failed platforms being re-published. */
|
|
179
|
+
platforms?: string[];
|
|
180
|
+
message?: string;
|
|
181
|
+
}
|
|
182
|
+
/** One place from GET /locations/search
|
|
183
|
+
* (@openapi block in backend/routes/api/v1/locations.js). */
|
|
184
|
+
export interface LocationPlace {
|
|
185
|
+
/** Facebook Place ID — use as `location_id`. */
|
|
186
|
+
id: string;
|
|
187
|
+
name: string;
|
|
188
|
+
address?: string | null;
|
|
189
|
+
city?: string | null;
|
|
190
|
+
country?: string | null;
|
|
191
|
+
}
|
|
192
|
+
/** GET /locations/search envelope — NOT the standard data/error envelope:
|
|
193
|
+
* on the documented degraded path (no Facebook account / missing permission)
|
|
194
|
+
* `error` is a human-readable STRING next to an empty `data`; the standard
|
|
195
|
+
* { code, message } object appears only on transport/HTTP failures. */
|
|
196
|
+
export interface LocationSearchResult {
|
|
197
|
+
data?: LocationPlace[];
|
|
198
|
+
error?: string | {
|
|
199
|
+
code: string;
|
|
200
|
+
message: string;
|
|
91
201
|
};
|
|
202
|
+
needsPermission?: boolean;
|
|
203
|
+
}
|
|
204
|
+
/** One track from GET /audio/search
|
|
205
|
+
* (@openapi block in backend/routes/api/v1/audio.js). */
|
|
206
|
+
export interface InstagramAudioTrack {
|
|
207
|
+
/** Use as `instagram.audio_id` on a reel. */
|
|
208
|
+
audio_id: string;
|
|
209
|
+
title?: string | null;
|
|
210
|
+
artist?: string | null;
|
|
211
|
+
duration_ms?: number | null;
|
|
212
|
+
/** Creator handle (original sounds only). */
|
|
213
|
+
ig_username?: string | null;
|
|
214
|
+
[k: string]: unknown;
|
|
215
|
+
}
|
|
216
|
+
/** GET /audio/search envelope — same nonstandard string-`error` convention
|
|
217
|
+
* as LocationSearchResult. */
|
|
218
|
+
export interface AudioSearchResult {
|
|
219
|
+
data?: InstagramAudioTrack[];
|
|
220
|
+
error?: string | {
|
|
221
|
+
code: string;
|
|
222
|
+
message: string;
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/** One record from GET /posts/recent-platform — normalized in
|
|
226
|
+
* backend/services/voice-fetcher/recentPlatformPostsService.js (:125-149). */
|
|
227
|
+
export interface RecentPlatformPost {
|
|
228
|
+
platform: string;
|
|
229
|
+
/** The platform's own post id — the stable dedupe key. */
|
|
230
|
+
id: string | null;
|
|
231
|
+
permalink: string | null;
|
|
232
|
+
/** Always a string; "" when the post has no caption. */
|
|
233
|
+
text: string;
|
|
234
|
+
format?: string;
|
|
235
|
+
media_count?: number;
|
|
236
|
+
timestamp?: string | null;
|
|
237
|
+
image_url?: string | null;
|
|
238
|
+
/** Video length in whole seconds; null for images / platforms without it. */
|
|
239
|
+
duration_seconds?: number | null;
|
|
240
|
+
metrics?: Record<string, unknown>;
|
|
241
|
+
engagement?: number | null;
|
|
242
|
+
impressions?: number | null;
|
|
243
|
+
engagement_rate?: number | null;
|
|
92
244
|
}
|
|
93
245
|
export interface MediaItem {
|
|
94
246
|
id: string;
|
|
@@ -170,11 +322,123 @@ export interface HashtagSet {
|
|
|
170
322
|
created_at: string;
|
|
171
323
|
updated_at: string;
|
|
172
324
|
}
|
|
325
|
+
/** Per-platform stats block inside AnalyticsOverview.platform_breakdown.
|
|
326
|
+
* Shape from backend/routes/api/v1/analytics.js (overview route). */
|
|
327
|
+
export interface AnalyticsPlatformBreakdown {
|
|
328
|
+
posts: number;
|
|
329
|
+
total_engagement: number;
|
|
330
|
+
total_impressions: number;
|
|
331
|
+
average_engagement: number;
|
|
332
|
+
/** 0 when total_impressions is below the shared minimum-impressions floor. */
|
|
333
|
+
engagement_rate: number;
|
|
334
|
+
}
|
|
335
|
+
/** `data` payload of GET /analytics/overview. The resolved range
|
|
336
|
+
* (`period`/`start_date`/`end_date`/`current_date`) rides top-level on the
|
|
337
|
+
* response envelope, not inside `data` — see getAnalyticsOverview(). */
|
|
173
338
|
export interface AnalyticsOverview {
|
|
174
339
|
total_posts: number;
|
|
340
|
+
total_platforms: number;
|
|
341
|
+
total_engagement: number;
|
|
175
342
|
total_impressions: number;
|
|
176
|
-
|
|
177
|
-
|
|
343
|
+
average_engagement_rate: number;
|
|
344
|
+
top_performing_platform: string | null;
|
|
345
|
+
platform_breakdown: Record<string, AnalyticsPlatformBreakdown>;
|
|
346
|
+
}
|
|
347
|
+
/** One connected platform that would reject the file
|
|
348
|
+
* (backend/services/media/mediaCompatibility.js getMediaWarnings). */
|
|
349
|
+
export interface MediaCompatWarning {
|
|
350
|
+
platform: string;
|
|
351
|
+
display_name: string;
|
|
352
|
+
reasons: string[];
|
|
353
|
+
}
|
|
354
|
+
/** Advisory compatibility block on /media/upload* and /media/check responses.
|
|
355
|
+
* Built by buildCompatibility() in backend/routes/api/v1/media.js:
|
|
356
|
+
* empty warnings = the file posts to every connected platform. */
|
|
357
|
+
export interface MediaCompatibility {
|
|
358
|
+
compatible: boolean;
|
|
359
|
+
warnings: MediaCompatWarning[];
|
|
360
|
+
/** One-line human summary, or null when fully compatible. */
|
|
361
|
+
summary: string | null;
|
|
362
|
+
}
|
|
363
|
+
/** POST /media/check response — the compatibility block is spread top-level
|
|
364
|
+
* next to `file` and `connected_platforms`; there is no `data` key
|
|
365
|
+
* (backend/routes/api/v1/media.js check route). */
|
|
366
|
+
export interface MediaCheckResult {
|
|
367
|
+
error?: {
|
|
368
|
+
code: string;
|
|
369
|
+
message: string;
|
|
370
|
+
};
|
|
371
|
+
file?: {
|
|
372
|
+
size_bytes: number | null;
|
|
373
|
+
mime: string | null;
|
|
374
|
+
size_known: boolean;
|
|
375
|
+
};
|
|
376
|
+
connected_platforms?: string[];
|
|
377
|
+
compatible?: boolean;
|
|
378
|
+
warnings?: MediaCompatWarning[];
|
|
379
|
+
summary?: string | null;
|
|
380
|
+
}
|
|
381
|
+
/** One folder from GET /folders — formatFolder in
|
|
382
|
+
* backend/routes/api/v1/folders.js (:15-23). */
|
|
383
|
+
export interface MediaFolder {
|
|
384
|
+
id: string;
|
|
385
|
+
name: string;
|
|
386
|
+
parent_id: string | null;
|
|
387
|
+
item_count?: number;
|
|
388
|
+
created_at?: string;
|
|
389
|
+
}
|
|
390
|
+
/** One row of GET /analytics/accounts `data`. `metrics` is the platform's
|
|
391
|
+
* account-level snapshot JSONB — counters are numbers; `note` (when present)
|
|
392
|
+
* explains non-obvious metric scope and must be relayed to the user. */
|
|
393
|
+
export interface AccountAnalyticsEntry {
|
|
394
|
+
platform: string;
|
|
395
|
+
platform_account_id?: string | null;
|
|
396
|
+
date?: string;
|
|
397
|
+
metrics?: {
|
|
398
|
+
followers?: number;
|
|
399
|
+
subscribers?: number;
|
|
400
|
+
posts?: number;
|
|
401
|
+
following?: number;
|
|
402
|
+
impressions?: number;
|
|
403
|
+
engagement?: number;
|
|
404
|
+
total_views?: number;
|
|
405
|
+
total_videos?: number;
|
|
406
|
+
note?: string;
|
|
407
|
+
[k: string]: number | string | undefined;
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
/** GET /analytics/best-times response — top-level, not the data/error
|
|
411
|
+
* envelope (backend/services/analytics/bestTimeService.js getBestTimes). */
|
|
412
|
+
export interface BestTimeRecommendation {
|
|
413
|
+
day: string;
|
|
414
|
+
/** "HH:00" in the resolved timezone. */
|
|
415
|
+
time: string;
|
|
416
|
+
score: number;
|
|
417
|
+
/** Number of posts behind the slot (own-data basis only). */
|
|
418
|
+
n?: number;
|
|
419
|
+
typical_engagement?: number;
|
|
420
|
+
}
|
|
421
|
+
export interface BestTimeGridCell {
|
|
422
|
+
day: string;
|
|
423
|
+
hour: number;
|
|
424
|
+
score: number;
|
|
425
|
+
[k: string]: unknown;
|
|
426
|
+
}
|
|
427
|
+
export interface BestTimesResult {
|
|
428
|
+
error?: {
|
|
429
|
+
code: string;
|
|
430
|
+
message: string;
|
|
431
|
+
};
|
|
432
|
+
platform?: string;
|
|
433
|
+
timezone?: string;
|
|
434
|
+
metric?: string;
|
|
435
|
+
window_days?: number;
|
|
436
|
+
sample_size?: number;
|
|
437
|
+
basis?: "own_data" | "defaults";
|
|
438
|
+
posts_needed?: number;
|
|
439
|
+
/** Absent on the defaults basis. */
|
|
440
|
+
grid?: BestTimeGridCell[];
|
|
441
|
+
recommendations?: BestTimeRecommendation[];
|
|
178
442
|
}
|
|
179
443
|
export interface PostAnalyticsPlatformEntry {
|
|
180
444
|
platform: string;
|
package/package.json
CHANGED