posterly-mcp-server 0.8.2 → 0.19.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/README.md +38 -3
- package/dist/generated/platform-manifest.d.ts +392 -0
- package/dist/generated/platform-manifest.js +695 -0
- package/dist/index.js +331 -1
- package/dist/lib/api-client.d.ts +391 -24
- package/dist/lib/api-client.js +176 -0
- package/dist/tools/audit-google-business-profile.d.ts +24 -0
- package/dist/tools/audit-google-business-profile.js +27 -0
- package/dist/tools/create-oauth-client.d.ts +40 -0
- package/dist/tools/create-oauth-client.js +20 -0
- package/dist/tools/create-post.d.ts +399 -20
- package/dist/tools/create-post.js +81 -78
- package/dist/tools/create-posts-batch.d.ts +567 -0
- package/dist/tools/create-posts-batch.js +38 -0
- package/dist/tools/create-signed-upload.d.ts +24 -0
- package/dist/tools/create-signed-upload.js +20 -0
- package/dist/tools/create-webhook.d.ts +36 -0
- package/dist/tools/create-webhook.js +20 -0
- package/dist/tools/delete-google-business-review-reply.d.ts +32 -0
- package/dist/tools/delete-google-business-review-reply.js +17 -0
- package/dist/tools/delete-oauth-client.d.ts +20 -0
- package/dist/tools/delete-oauth-client.js +13 -0
- package/dist/tools/delete-post-group.d.ts +20 -0
- package/dist/tools/delete-post-group.js +13 -0
- package/dist/tools/delete-webhook.d.ts +20 -0
- package/dist/tools/delete-webhook.js +13 -0
- package/dist/tools/disconnect-account.d.ts +20 -0
- package/dist/tools/disconnect-account.js +22 -0
- package/dist/tools/generate-image.d.ts +4 -4
- package/dist/tools/generate-video.d.ts +59 -0
- package/dist/tools/generate-video.js +34 -0
- package/dist/tools/get-connect-link.d.ts +24 -0
- package/dist/tools/get-connect-link.js +46 -0
- package/dist/tools/get-google-business-review-link.d.ts +24 -0
- package/dist/tools/get-google-business-review-link.js +19 -0
- package/dist/tools/get-platform-schema.d.ts +24 -0
- package/dist/tools/get-platform-schema.js +44 -0
- package/dist/tools/get-post-missing.d.ts +16 -0
- package/dist/tools/get-post-missing.js +12 -0
- package/dist/tools/get-video-job.d.ts +24 -0
- package/dist/tools/get-video-job.js +31 -0
- package/dist/tools/get-video-options.d.ts +8 -0
- package/dist/tools/get-video-options.js +26 -0
- package/dist/tools/get-x-posting-quota.d.ts +16 -0
- package/dist/tools/get-x-posting-quota.js +21 -0
- package/dist/tools/list-activity.d.ts +32 -0
- package/dist/tools/list-activity.js +35 -0
- package/dist/tools/list-google-business-reviews.d.ts +32 -0
- package/dist/tools/list-google-business-reviews.js +28 -0
- package/dist/tools/list-oauth-clients.d.ts +8 -0
- package/dist/tools/list-oauth-clients.js +15 -0
- package/dist/tools/list-platforms.d.ts +16 -0
- package/dist/tools/list-platforms.js +20 -0
- package/dist/tools/list-posts.d.ts +3 -3
- package/dist/tools/list-posts.js +3 -2
- package/dist/tools/list-webhooks.d.ts +16 -0
- package/dist/tools/list-webhooks.js +24 -0
- package/dist/tools/reply-google-business-review.d.ts +36 -0
- package/dist/tools/reply-google-business-review.js +18 -0
- package/dist/tools/run-video-function.d.ts +24 -0
- package/dist/tools/run-video-function.js +25 -0
- package/dist/tools/suggest-google-business-review-reply.d.ts +48 -0
- package/dist/tools/suggest-google-business-review-reply.js +27 -0
- package/dist/tools/test-webhook.d.ts +20 -0
- package/dist/tools/test-webhook.js +14 -0
- package/dist/tools/trigger-platform-helper.d.ts +28 -0
- package/dist/tools/trigger-platform-helper.js +22 -0
- package/dist/tools/update-oauth-client.d.ts +44 -0
- package/dist/tools/update-oauth-client.js +21 -0
- package/dist/tools/update-post-release-id.d.ts +28 -0
- package/dist/tools/update-post-release-id.js +18 -0
- package/dist/tools/update-post-status.d.ts +28 -0
- package/dist/tools/update-post-status.js +23 -0
- package/dist/tools/update-post.js +1 -1
- package/dist/tools/update-webhook.d.ts +40 -0
- package/dist/tools/update-webhook.js +21 -0
- package/dist/tools/upload-media-from-url.d.ts +24 -0
- package/dist/tools/upload-media-from-url.js +26 -0
- package/dist/tools/webhook-events.d.ts +3 -0
- package/dist/tools/webhook-events.js +13 -0
- package/package.json +1 -1
- package/src/generated/platform-manifest.ts +695 -0
- package/src/index.ts +496 -1
- package/src/lib/api-client.ts +497 -19
- package/src/tools/audit-google-business-profile.ts +38 -0
- package/src/tools/create-oauth-client.ts +36 -0
- package/src/tools/create-post.ts +91 -94
- package/src/tools/create-posts-batch.ts +48 -0
- package/src/tools/create-signed-upload.ts +27 -0
- package/src/tools/create-webhook.ts +35 -0
- package/src/tools/delete-google-business-review-reply.ts +30 -0
- package/src/tools/delete-oauth-client.ts +23 -0
- package/src/tools/delete-post-group.ts +17 -0
- package/src/tools/delete-webhook.ts +18 -0
- package/src/tools/disconnect-account.ts +30 -0
- package/src/tools/generate-video.ts +38 -0
- package/src/tools/get-connect-link.ts +56 -0
- package/src/tools/get-google-business-review-link.ts +30 -0
- package/src/tools/get-platform-schema.ts +52 -0
- package/src/tools/get-post-missing.ts +17 -0
- package/src/tools/get-video-job.ts +36 -0
- package/src/tools/get-video-options.ts +30 -0
- package/src/tools/get-x-posting-quota.ts +25 -0
- package/src/tools/list-activity.ts +51 -0
- package/src/tools/list-google-business-reviews.ts +43 -0
- package/src/tools/list-oauth-clients.ts +18 -0
- package/src/tools/list-platforms.ts +25 -0
- package/src/tools/list-posts.ts +3 -2
- package/src/tools/list-webhooks.ts +30 -0
- package/src/tools/reply-google-business-review.ts +32 -0
- package/src/tools/run-video-function.ts +32 -0
- package/src/tools/suggest-google-business-review-reply.ts +44 -0
- package/src/tools/test-webhook.ts +18 -0
- package/src/tools/trigger-platform-helper.ts +34 -0
- package/src/tools/update-oauth-client.ts +38 -0
- package/src/tools/update-post-release-id.ts +26 -0
- package/src/tools/update-post-status.ts +31 -0
- package/src/tools/update-post.ts +1 -1
- package/src/tools/update-webhook.ts +37 -0
- package/src/tools/upload-media-from-url.ts +33 -0
- package/src/tools/webhook-events.ts +16 -0
package/src/lib/api-client.ts
CHANGED
|
@@ -80,6 +80,37 @@ export interface InstagramPostSettings {
|
|
|
80
80
|
|
|
81
81
|
export type PlatformPostSettings = Record<string, unknown>;
|
|
82
82
|
|
|
83
|
+
export type CreatePostPayload = {
|
|
84
|
+
account_id?: string;
|
|
85
|
+
username?: string;
|
|
86
|
+
platform?: string;
|
|
87
|
+
caption: string;
|
|
88
|
+
scheduled_at?: string;
|
|
89
|
+
post_type?: string;
|
|
90
|
+
media_url?: string;
|
|
91
|
+
media_urls?: string[];
|
|
92
|
+
metadata?: Record<string, unknown>;
|
|
93
|
+
settings?: PlatformPostSettings;
|
|
94
|
+
reel_cover_url?: string;
|
|
95
|
+
reel_cover_method?: string;
|
|
96
|
+
reel_thumb_offset?: number;
|
|
97
|
+
workspace_id?: string;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export type CreatePostResponse = {
|
|
101
|
+
post: Post;
|
|
102
|
+
workspace: { id: string; name: string; is_personal: boolean; resolved_from: 'explicit' | 'account' | 'personal' };
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type BatchCreatePostsResponse = {
|
|
106
|
+
posts: Array<CreatePostResponse & { index: number; replayed: boolean }>;
|
|
107
|
+
errors: Array<{ index: number; status: number; error: string; validation_errors?: unknown }>;
|
|
108
|
+
total: number;
|
|
109
|
+
created: number;
|
|
110
|
+
replayed: number;
|
|
111
|
+
failed: number;
|
|
112
|
+
};
|
|
113
|
+
|
|
83
114
|
export interface Slot {
|
|
84
115
|
time: string;
|
|
85
116
|
local_time: string;
|
|
@@ -180,6 +211,172 @@ export interface PostAnalyticsResponse {
|
|
|
180
211
|
offset: number;
|
|
181
212
|
}
|
|
182
213
|
|
|
214
|
+
export interface GoogleBusinessReview {
|
|
215
|
+
name?: string;
|
|
216
|
+
reviewId?: string;
|
|
217
|
+
reviewer?: { displayName?: string; profilePhotoUrl?: string };
|
|
218
|
+
starRating: number;
|
|
219
|
+
comment?: string;
|
|
220
|
+
createTime?: string;
|
|
221
|
+
updateTime?: string;
|
|
222
|
+
reviewReply?: Record<string, unknown>;
|
|
223
|
+
locationId?: string | null;
|
|
224
|
+
locationName?: string | null;
|
|
225
|
+
businessName?: string | null;
|
|
226
|
+
socialAccountId?: number;
|
|
227
|
+
account_id?: number;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface GoogleBusinessReviewsResponse {
|
|
231
|
+
reviews: GoogleBusinessReview[];
|
|
232
|
+
total: number;
|
|
233
|
+
locations: Array<Record<string, unknown>>;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface GoogleBusinessReviewLinkResponse {
|
|
237
|
+
reviewLink: string;
|
|
238
|
+
placeId: string;
|
|
239
|
+
businessName: string;
|
|
240
|
+
locationId: string | null;
|
|
241
|
+
account_id: number;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface ActivityItem {
|
|
245
|
+
id: string;
|
|
246
|
+
type: 'activity' | 'publish';
|
|
247
|
+
post_id: number | null;
|
|
248
|
+
action?: string | null;
|
|
249
|
+
description?: string | null;
|
|
250
|
+
platform?: string | null;
|
|
251
|
+
outcome?: string | null;
|
|
252
|
+
error_code?: string | null;
|
|
253
|
+
error_message?: string | null;
|
|
254
|
+
http_status?: number | null;
|
|
255
|
+
retry_number?: number | null;
|
|
256
|
+
duration_ms?: number | null;
|
|
257
|
+
pipeline_step?: string | null;
|
|
258
|
+
metadata?: Record<string, unknown> | null;
|
|
259
|
+
context?: Record<string, unknown> | null;
|
|
260
|
+
created_at: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface ActivityResponse {
|
|
264
|
+
items: ActivityItem[];
|
|
265
|
+
total: number;
|
|
266
|
+
limit: number;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface ApiWebhook {
|
|
270
|
+
id: string;
|
|
271
|
+
workspace_id: string | null;
|
|
272
|
+
url: string;
|
|
273
|
+
description: string | null;
|
|
274
|
+
events: string[];
|
|
275
|
+
is_active: boolean;
|
|
276
|
+
created_at: string;
|
|
277
|
+
updated_at: string | null;
|
|
278
|
+
last_delivery_at: string | null;
|
|
279
|
+
last_delivery_status: number | null;
|
|
280
|
+
last_error: string | null;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export interface WebhookResponse {
|
|
284
|
+
webhook: ApiWebhook;
|
|
285
|
+
secret?: string;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export interface PlatformSchema {
|
|
289
|
+
id: string;
|
|
290
|
+
aliases: string[];
|
|
291
|
+
label: string;
|
|
292
|
+
status: 'supported' | 'planned';
|
|
293
|
+
summary: string;
|
|
294
|
+
content_limit: number | null;
|
|
295
|
+
media: Record<string, unknown>;
|
|
296
|
+
post_types: string[];
|
|
297
|
+
analytics_supported: boolean;
|
|
298
|
+
settings_schema: {
|
|
299
|
+
fields: Array<Record<string, unknown>>;
|
|
300
|
+
example: Record<string, unknown>;
|
|
301
|
+
};
|
|
302
|
+
helper_tools: Array<Record<string, unknown>>;
|
|
303
|
+
native_features: string[];
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export interface ConnectOption {
|
|
307
|
+
platform: string;
|
|
308
|
+
aliases: string[];
|
|
309
|
+
label: string;
|
|
310
|
+
status: 'supported' | 'planned';
|
|
311
|
+
method: 'dashboard_oauth' | 'manual_credentials' | 'planned';
|
|
312
|
+
provider_platforms: string[];
|
|
313
|
+
dashboard_url: string;
|
|
314
|
+
connection_url: string | null;
|
|
315
|
+
oauth_url: string | null;
|
|
316
|
+
supports_direct_oauth_url: boolean;
|
|
317
|
+
requires_browser_session: boolean;
|
|
318
|
+
configured: boolean | null;
|
|
319
|
+
env_requirements: Array<Record<string, unknown>>;
|
|
320
|
+
missing_env: string[][];
|
|
321
|
+
scopes: string[];
|
|
322
|
+
credential_fields: Array<Record<string, unknown>>;
|
|
323
|
+
notes: string[];
|
|
324
|
+
connected_count?: number;
|
|
325
|
+
connected_accounts?: Account[];
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export interface OAuthDeveloperClient {
|
|
329
|
+
id: string;
|
|
330
|
+
client_id: string;
|
|
331
|
+
client_name: string;
|
|
332
|
+
description?: string | null;
|
|
333
|
+
homepage?: string | null;
|
|
334
|
+
allowed_redirect_uris: string[];
|
|
335
|
+
default_scopes: string[];
|
|
336
|
+
is_active: boolean;
|
|
337
|
+
created_at?: string;
|
|
338
|
+
updated_at?: string;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export interface VideoJob {
|
|
342
|
+
id: string;
|
|
343
|
+
status: string;
|
|
344
|
+
prompt: string;
|
|
345
|
+
model: string;
|
|
346
|
+
duration_seconds: number;
|
|
347
|
+
aspect_ratio?: string;
|
|
348
|
+
resolution?: string;
|
|
349
|
+
generation_mode?: string | null;
|
|
350
|
+
credit_cost: number;
|
|
351
|
+
included_credit_cost?: number;
|
|
352
|
+
purchased_credit_cost?: number;
|
|
353
|
+
source_image_url?: string | null;
|
|
354
|
+
end_image_url?: string | null;
|
|
355
|
+
source_video_url?: string | null;
|
|
356
|
+
reference_images?: unknown;
|
|
357
|
+
generate_audio?: boolean | null;
|
|
358
|
+
video_url?: string | null;
|
|
359
|
+
error_message?: string | null;
|
|
360
|
+
created_at: string;
|
|
361
|
+
started_at?: string | null;
|
|
362
|
+
completed_at?: string | null;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export interface XPostingQuotaResponse {
|
|
366
|
+
workspace_id: string | null;
|
|
367
|
+
tier: string | null;
|
|
368
|
+
base_posts: number;
|
|
369
|
+
addon_posts: number;
|
|
370
|
+
total_posts: number;
|
|
371
|
+
used_posts: number;
|
|
372
|
+
remaining_posts: number;
|
|
373
|
+
current_period_start: string;
|
|
374
|
+
current_period_end: string;
|
|
375
|
+
urls_blocked: boolean;
|
|
376
|
+
addon?: Record<string, unknown>;
|
|
377
|
+
plans?: Array<Record<string, unknown>>;
|
|
378
|
+
}
|
|
379
|
+
|
|
183
380
|
export class PosterlyClient {
|
|
184
381
|
private baseUrl: string;
|
|
185
382
|
private apiKey: string;
|
|
@@ -234,6 +431,58 @@ export class PosterlyClient {
|
|
|
234
431
|
return data.accounts;
|
|
235
432
|
}
|
|
236
433
|
|
|
434
|
+
async disconnectAccount(accountId: string): Promise<Record<string, any>> {
|
|
435
|
+
return this.request('DELETE', `/accounts/${encodeURIComponent(accountId)}`);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
async getConnectLink(params?: {
|
|
439
|
+
platform?: string;
|
|
440
|
+
workspace_id?: string;
|
|
441
|
+
include_planned?: boolean;
|
|
442
|
+
}): Promise<{ connect?: ConnectOption; connect_options?: ConnectOption[] }> {
|
|
443
|
+
const searchParams = new URLSearchParams();
|
|
444
|
+
if (params?.workspace_id) searchParams.set('workspace_id', params.workspace_id);
|
|
445
|
+
if (params?.include_planned) searchParams.set('include_planned', 'true');
|
|
446
|
+
const qs = searchParams.toString();
|
|
447
|
+
const path = params?.platform
|
|
448
|
+
? `/connect/${encodeURIComponent(params.platform)}`
|
|
449
|
+
: '/connect';
|
|
450
|
+
return this.request('GET', `${path}${qs ? `?${qs}` : ''}`);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
async listOAuthClients(): Promise<{ clients: OAuthDeveloperClient[] }> {
|
|
454
|
+
return this.request('GET', '/oauth/clients');
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
async createOAuthClient(data: {
|
|
458
|
+
client_name: string;
|
|
459
|
+
description?: string;
|
|
460
|
+
homepage?: string;
|
|
461
|
+
allowed_redirect_uris: string[];
|
|
462
|
+
default_scopes: string[];
|
|
463
|
+
is_active?: boolean;
|
|
464
|
+
}): Promise<{ client: OAuthDeveloperClient }> {
|
|
465
|
+
return this.request('POST', '/oauth/clients', data);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async updateOAuthClient(
|
|
469
|
+
clientId: string,
|
|
470
|
+
data: {
|
|
471
|
+
client_name?: string;
|
|
472
|
+
description?: string;
|
|
473
|
+
homepage?: string | null;
|
|
474
|
+
allowed_redirect_uris?: string[];
|
|
475
|
+
default_scopes?: string[];
|
|
476
|
+
is_active?: boolean;
|
|
477
|
+
},
|
|
478
|
+
): Promise<{ client: OAuthDeveloperClient }> {
|
|
479
|
+
return this.request('PATCH', `/oauth/clients/${encodeURIComponent(clientId)}`, data);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
async deleteOAuthClient(clientId: string): Promise<{ deleted: boolean; client_id: string }> {
|
|
483
|
+
return this.request('DELETE', `/oauth/clients/${encodeURIComponent(clientId)}`);
|
|
484
|
+
}
|
|
485
|
+
|
|
237
486
|
async listBrands(params?: { workspace_id?: string }): Promise<Brand[]> {
|
|
238
487
|
const searchParams = new URLSearchParams();
|
|
239
488
|
if (params?.workspace_id) searchParams.set('workspace_id', params.workspace_id);
|
|
@@ -275,32 +524,22 @@ export class PosterlyClient {
|
|
|
275
524
|
return this.request('GET', `/posts${qs ? `?${qs}` : ''}`);
|
|
276
525
|
}
|
|
277
526
|
|
|
278
|
-
async createPost(data: {
|
|
279
|
-
account_id?: string;
|
|
280
|
-
username?: string;
|
|
281
|
-
platform?: string;
|
|
282
|
-
caption: string;
|
|
283
|
-
scheduled_at?: string;
|
|
284
|
-
post_type?: string;
|
|
285
|
-
media_url?: string;
|
|
286
|
-
media_urls?: string[];
|
|
287
|
-
metadata?: Record<string, unknown>;
|
|
288
|
-
settings?: PlatformPostSettings;
|
|
289
|
-
reel_cover_url?: string;
|
|
290
|
-
reel_cover_method?: string;
|
|
291
|
-
reel_thumb_offset?: number;
|
|
292
|
-
workspace_id?: string;
|
|
293
|
-
}): Promise<{
|
|
294
|
-
post: Post;
|
|
295
|
-
workspace: { id: string; name: string; is_personal: boolean; resolved_from: 'explicit' | 'account' | 'personal' };
|
|
296
|
-
}> {
|
|
527
|
+
async createPost(data: CreatePostPayload): Promise<CreatePostResponse> {
|
|
297
528
|
return this.request('POST', '/posts', data);
|
|
298
529
|
}
|
|
299
530
|
|
|
531
|
+
async createPostsBatch(data: { posts: CreatePostPayload[] }): Promise<BatchCreatePostsResponse> {
|
|
532
|
+
return this.request('POST', '/posts/batch', data);
|
|
533
|
+
}
|
|
534
|
+
|
|
300
535
|
async getPost(id: number): Promise<{ post: Post }> {
|
|
301
536
|
return this.request('GET', `/posts/${id}`);
|
|
302
537
|
}
|
|
303
538
|
|
|
539
|
+
async getPostMissing(id: number): Promise<Record<string, any>> {
|
|
540
|
+
return this.request('GET', `/posts/${id}/missing`);
|
|
541
|
+
}
|
|
542
|
+
|
|
304
543
|
async updatePost(
|
|
305
544
|
id: number,
|
|
306
545
|
data: {
|
|
@@ -323,6 +562,24 @@ export class PosterlyClient {
|
|
|
323
562
|
return this.request('DELETE', `/posts/${id}`);
|
|
324
563
|
}
|
|
325
564
|
|
|
565
|
+
async updatePostStatus(
|
|
566
|
+
id: number,
|
|
567
|
+
data: { status: 'scheduled' | 'paused' | 'draft'; scheduled_at?: string },
|
|
568
|
+
): Promise<Record<string, any>> {
|
|
569
|
+
return this.request('PUT', `/posts/${id}/status`, data);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
async updatePostReleaseId(
|
|
573
|
+
id: number,
|
|
574
|
+
data: { release_id: string; group_id?: string },
|
|
575
|
+
): Promise<Record<string, any>> {
|
|
576
|
+
return this.request('PUT', `/posts/${id}/release-id`, data);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
async deletePostGroup(groupId: string): Promise<Record<string, any>> {
|
|
580
|
+
return this.request('DELETE', `/posts/group/${encodeURIComponent(groupId)}?confirm=true`);
|
|
581
|
+
}
|
|
582
|
+
|
|
326
583
|
async generateImage(data: {
|
|
327
584
|
prompt: string;
|
|
328
585
|
aspect_ratio?: string;
|
|
@@ -347,6 +604,49 @@ export class PosterlyClient {
|
|
|
347
604
|
return this.request('POST', '/ai/generate-image', data);
|
|
348
605
|
}
|
|
349
606
|
|
|
607
|
+
async getVideoOptions(): Promise<Record<string, any>> {
|
|
608
|
+
return this.request('GET', '/ai/video-options');
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
async runVideoFunction(data: {
|
|
612
|
+
identifier: string;
|
|
613
|
+
functionName: string;
|
|
614
|
+
params?: Record<string, unknown>;
|
|
615
|
+
}): Promise<Record<string, any>> {
|
|
616
|
+
return this.request('POST', '/ai/video-function', data);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
async generateVideo(data: {
|
|
620
|
+
prompt: string;
|
|
621
|
+
negative_prompt?: string;
|
|
622
|
+
aspect_ratio?: '16:9' | '9:16';
|
|
623
|
+
duration_seconds?: 4 | 6 | 8;
|
|
624
|
+
resolution?: '720p' | '1080p';
|
|
625
|
+
model?: 'fast' | 'standard';
|
|
626
|
+
image_url?: string;
|
|
627
|
+
end_image_url?: string;
|
|
628
|
+
reference_images?: Array<{ url: string; type: 'character' | 'object' | 'scene' }>;
|
|
629
|
+
generate_audio?: boolean;
|
|
630
|
+
source_video_url?: string;
|
|
631
|
+
}): Promise<Record<string, any>> {
|
|
632
|
+
return this.request('POST', '/ai/generate-video', data);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
async getVideoJob(params?: {
|
|
636
|
+
job_id?: string;
|
|
637
|
+
status?: string;
|
|
638
|
+
limit?: number;
|
|
639
|
+
}): Promise<{ job?: VideoJob; jobs?: VideoJob[] }> {
|
|
640
|
+
if (params?.job_id) {
|
|
641
|
+
return this.request('GET', `/ai/video-jobs/${encodeURIComponent(params.job_id)}`);
|
|
642
|
+
}
|
|
643
|
+
const searchParams = new URLSearchParams();
|
|
644
|
+
if (params?.status) searchParams.set('status', params.status);
|
|
645
|
+
if (params?.limit) searchParams.set('limit', String(params.limit));
|
|
646
|
+
const qs = searchParams.toString();
|
|
647
|
+
return this.request('GET', `/ai/video-jobs${qs ? `?${qs}` : ''}`);
|
|
648
|
+
}
|
|
649
|
+
|
|
350
650
|
async findAvailableSlots(params?: {
|
|
351
651
|
account_ids?: string[];
|
|
352
652
|
timezone?: string;
|
|
@@ -392,6 +692,172 @@ export class PosterlyClient {
|
|
|
392
692
|
return this.request('GET', `/analytics/posts?${searchParams.toString()}`);
|
|
393
693
|
}
|
|
394
694
|
|
|
695
|
+
async listGoogleBusinessReviews(params?: {
|
|
696
|
+
workspace_id?: string;
|
|
697
|
+
account_id?: number;
|
|
698
|
+
location_id?: string;
|
|
699
|
+
rating?: number;
|
|
700
|
+
unanswered?: boolean;
|
|
701
|
+
}): Promise<GoogleBusinessReviewsResponse> {
|
|
702
|
+
const searchParams = new URLSearchParams();
|
|
703
|
+
if (params?.workspace_id) searchParams.set('workspace_id', params.workspace_id);
|
|
704
|
+
if (params?.account_id) searchParams.set('account_id', String(params.account_id));
|
|
705
|
+
if (params?.location_id) searchParams.set('location_id', params.location_id);
|
|
706
|
+
if (params?.rating) searchParams.set('rating', String(params.rating));
|
|
707
|
+
if (params?.unanswered) searchParams.set('unanswered', 'true');
|
|
708
|
+
const qs = searchParams.toString();
|
|
709
|
+
return this.request('GET', `/google-business/reviews${qs ? `?${qs}` : ''}`);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
async getGoogleBusinessReviewLink(params: {
|
|
713
|
+
workspace_id?: string;
|
|
714
|
+
account_id?: number;
|
|
715
|
+
location_id?: string;
|
|
716
|
+
}): Promise<GoogleBusinessReviewLinkResponse> {
|
|
717
|
+
const searchParams = new URLSearchParams();
|
|
718
|
+
if (params.workspace_id) searchParams.set('workspace_id', params.workspace_id);
|
|
719
|
+
if (params.account_id) searchParams.set('account_id', String(params.account_id));
|
|
720
|
+
if (params.location_id) searchParams.set('location_id', params.location_id);
|
|
721
|
+
return this.request('GET', `/google-business/review-link?${searchParams.toString()}`);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
async auditGoogleBusinessProfile(params: {
|
|
725
|
+
workspace_id?: string;
|
|
726
|
+
account_id?: number;
|
|
727
|
+
location_id?: string;
|
|
728
|
+
}): Promise<Record<string, any>> {
|
|
729
|
+
const searchParams = new URLSearchParams();
|
|
730
|
+
if (params.workspace_id) searchParams.set('workspace_id', params.workspace_id);
|
|
731
|
+
if (params.account_id) searchParams.set('account_id', String(params.account_id));
|
|
732
|
+
if (params.location_id) searchParams.set('location_id', params.location_id);
|
|
733
|
+
return this.request('GET', `/google-business/audit?${searchParams.toString()}`);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
async suggestGoogleBusinessReviewReply(data: {
|
|
737
|
+
workspace_id?: string;
|
|
738
|
+
account_id?: number;
|
|
739
|
+
location_id?: string;
|
|
740
|
+
review_text?: string;
|
|
741
|
+
star_rating: number;
|
|
742
|
+
reviewer_name?: string;
|
|
743
|
+
business_name?: string;
|
|
744
|
+
tone?: 'professional' | 'friendly' | 'apologetic';
|
|
745
|
+
count?: number;
|
|
746
|
+
}): Promise<Record<string, any>> {
|
|
747
|
+
return this.request('POST', '/google-business/reviews/suggest-reply', data);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
async replyGoogleBusinessReview(data: {
|
|
751
|
+
workspace_id?: string;
|
|
752
|
+
account_id?: number;
|
|
753
|
+
location_id?: string;
|
|
754
|
+
review_name: string;
|
|
755
|
+
comment: string;
|
|
756
|
+
}): Promise<Record<string, any>> {
|
|
757
|
+
return this.request('POST', '/google-business/reviews/reply', data);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
async deleteGoogleBusinessReviewReply(data: {
|
|
761
|
+
workspace_id?: string;
|
|
762
|
+
account_id?: number;
|
|
763
|
+
location_id?: string;
|
|
764
|
+
review_name: string;
|
|
765
|
+
}): Promise<Record<string, any>> {
|
|
766
|
+
return this.request('DELETE', '/google-business/reviews/reply', data);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
async listActivity(params?: {
|
|
770
|
+
workspace_id?: string;
|
|
771
|
+
post_id?: number;
|
|
772
|
+
since?: string;
|
|
773
|
+
type?: 'all' | 'activity' | 'publish';
|
|
774
|
+
limit?: number;
|
|
775
|
+
}): Promise<ActivityResponse> {
|
|
776
|
+
const searchParams = new URLSearchParams();
|
|
777
|
+
if (params?.workspace_id) searchParams.set('workspace_id', params.workspace_id);
|
|
778
|
+
if (params?.post_id) searchParams.set('post_id', String(params.post_id));
|
|
779
|
+
if (params?.since) searchParams.set('since', params.since);
|
|
780
|
+
if (params?.type) searchParams.set('type', params.type);
|
|
781
|
+
if (params?.limit) searchParams.set('limit', String(params.limit));
|
|
782
|
+
const qs = searchParams.toString();
|
|
783
|
+
return this.request('GET', `/activity${qs ? `?${qs}` : ''}`);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
async listWebhooks(params?: { workspace_id?: string }): Promise<{ webhooks: ApiWebhook[] }> {
|
|
787
|
+
const searchParams = new URLSearchParams();
|
|
788
|
+
if (params?.workspace_id) searchParams.set('workspace_id', params.workspace_id);
|
|
789
|
+
const qs = searchParams.toString();
|
|
790
|
+
return this.request('GET', `/webhooks${qs ? `?${qs}` : ''}`);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
async createWebhook(data: {
|
|
794
|
+
url: string;
|
|
795
|
+
events?: string[];
|
|
796
|
+
workspace_id?: string;
|
|
797
|
+
description?: string;
|
|
798
|
+
is_active?: boolean;
|
|
799
|
+
}): Promise<WebhookResponse> {
|
|
800
|
+
return this.request('POST', '/webhooks', data);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
async updateWebhook(
|
|
804
|
+
id: string,
|
|
805
|
+
data: {
|
|
806
|
+
url?: string;
|
|
807
|
+
events?: string[];
|
|
808
|
+
workspace_id?: string | null;
|
|
809
|
+
description?: string | null;
|
|
810
|
+
is_active?: boolean;
|
|
811
|
+
},
|
|
812
|
+
): Promise<WebhookResponse> {
|
|
813
|
+
return this.request('PATCH', `/webhooks/${encodeURIComponent(id)}`, data);
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
async deleteWebhook(id: string): Promise<{ deleted: boolean; id: string }> {
|
|
817
|
+
return this.request('DELETE', `/webhooks/${encodeURIComponent(id)}`);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
async testWebhook(id: string): Promise<{ delivery: Record<string, unknown> }> {
|
|
821
|
+
return this.request('POST', `/webhooks/${encodeURIComponent(id)}/test`, {});
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
async listPlatforms(params?: { include_planned?: boolean }): Promise<{ platforms: PlatformSchema[] }> {
|
|
825
|
+
const searchParams = new URLSearchParams();
|
|
826
|
+
if (params?.include_planned) searchParams.set('include_planned', 'true');
|
|
827
|
+
const qs = searchParams.toString();
|
|
828
|
+
return this.request('GET', `/platforms${qs ? `?${qs}` : ''}`);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
async getPlatformSchema(params: {
|
|
832
|
+
account_id?: string;
|
|
833
|
+
platform?: string;
|
|
834
|
+
include_planned?: boolean;
|
|
835
|
+
}): Promise<{ account?: Record<string, unknown>; schema?: PlatformSchema; platform?: PlatformSchema; platforms?: PlatformSchema[] }> {
|
|
836
|
+
if (params.account_id) {
|
|
837
|
+
return this.request('GET', `/accounts/${encodeURIComponent(params.account_id)}/schema`);
|
|
838
|
+
}
|
|
839
|
+
const searchParams = new URLSearchParams();
|
|
840
|
+
if (params.platform) searchParams.set('platform', params.platform);
|
|
841
|
+
if (params.include_planned) searchParams.set('include_planned', 'true');
|
|
842
|
+
return this.request('GET', `/platforms?${searchParams.toString()}`);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
async triggerPlatformHelper(data: {
|
|
846
|
+
helper: string;
|
|
847
|
+
account_id?: string;
|
|
848
|
+
platform?: string;
|
|
849
|
+
params?: Record<string, unknown>;
|
|
850
|
+
}): Promise<{ helper: string; account: Record<string, unknown> | null; result: unknown }> {
|
|
851
|
+
return this.request('POST', '/platforms/trigger', data);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
async getXPostingQuota(params?: { workspace_id?: string }): Promise<XPostingQuotaResponse> {
|
|
855
|
+
const searchParams = new URLSearchParams();
|
|
856
|
+
if (params?.workspace_id) searchParams.set('workspace_id', params.workspace_id);
|
|
857
|
+
const qs = searchParams.toString();
|
|
858
|
+
return this.request('GET', `/x-posting/quota${qs ? `?${qs}` : ''}`);
|
|
859
|
+
}
|
|
860
|
+
|
|
395
861
|
async getSignedUploadUrl(
|
|
396
862
|
filename: string,
|
|
397
863
|
contentType: string,
|
|
@@ -459,6 +925,18 @@ export class PosterlyClient {
|
|
|
459
925
|
content_type: contentType,
|
|
460
926
|
});
|
|
461
927
|
}
|
|
928
|
+
|
|
929
|
+
async uploadMediaFromUrl(input: {
|
|
930
|
+
url: string;
|
|
931
|
+
filename?: string;
|
|
932
|
+
contentType?: string;
|
|
933
|
+
}): Promise<{ url: string; path: string; source_url: string; content_type: string; size: number }> {
|
|
934
|
+
return this.request('POST', '/media/upload-from-url', {
|
|
935
|
+
url: input.url,
|
|
936
|
+
filename: input.filename,
|
|
937
|
+
content_type: input.contentType,
|
|
938
|
+
});
|
|
939
|
+
}
|
|
462
940
|
}
|
|
463
941
|
|
|
464
942
|
function guessContentType(filename: string): string {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { PosterlyClient } from '../lib/api-client.js';
|
|
3
|
+
|
|
4
|
+
export const auditGoogleBusinessProfileTool = {
|
|
5
|
+
name: 'audit_google_business_profile',
|
|
6
|
+
description:
|
|
7
|
+
'Run a live local-profile audit for a connected Google Business Profile location, including completeness, categories, media, attributes, reviews, and recommendations.',
|
|
8
|
+
inputSchema: z.object({
|
|
9
|
+
workspace_id: z.string().optional().describe('Filter to a workspace ID from whoami.'),
|
|
10
|
+
account_id: z.number().int().positive().optional().describe('Google Business account ID from list_accounts.'),
|
|
11
|
+
location_id: z.string().optional().describe('Google Business location/platform_user_id.'),
|
|
12
|
+
}),
|
|
13
|
+
|
|
14
|
+
async execute(
|
|
15
|
+
client: PosterlyClient,
|
|
16
|
+
input: {
|
|
17
|
+
workspace_id?: string;
|
|
18
|
+
account_id?: number;
|
|
19
|
+
location_id?: string;
|
|
20
|
+
},
|
|
21
|
+
) {
|
|
22
|
+
const result = await client.auditGoogleBusinessProfile(input);
|
|
23
|
+
const audit = result.audit || {};
|
|
24
|
+
const recommendations = Array.isArray(audit.recommendations) ? audit.recommendations : [];
|
|
25
|
+
const lines = [
|
|
26
|
+
`Google Business audit: ${audit.businessName || 'Unknown business'}`,
|
|
27
|
+
`Score: ${audit.overallScore ?? 'n/a'} (${audit.overallGrade || 'n/a'})`,
|
|
28
|
+
`Fetched: ${result.fetchedAt || 'unknown'}`,
|
|
29
|
+
];
|
|
30
|
+
if (recommendations.length > 0) {
|
|
31
|
+
lines.push('Top recommendations:');
|
|
32
|
+
for (const rec of recommendations.slice(0, 5)) {
|
|
33
|
+
lines.push(`- ${rec.priority || 'medium'}: ${rec.description || rec.title || 'Recommendation'}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return lines.join('\n');
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { PosterlyClient } from '../lib/api-client.js';
|
|
3
|
+
|
|
4
|
+
const scopeSchema = z.enum(['accounts:read', 'accounts:write', 'posts:read', 'posts:write', 'media:write', 'analytics:read']);
|
|
5
|
+
|
|
6
|
+
export const createOAuthClientTool = {
|
|
7
|
+
name: 'create_oauth_client',
|
|
8
|
+
description:
|
|
9
|
+
'Create a public OAuth 2.1 + PKCE developer client. WRITE: confirm app name, redirect URIs, and scopes with the user before calling.',
|
|
10
|
+
inputSchema: z.object({
|
|
11
|
+
client_name: z.string().min(1).max(120),
|
|
12
|
+
description: z.string().max(500).optional(),
|
|
13
|
+
homepage: z.string().url().optional(),
|
|
14
|
+
allowed_redirect_uris: z.array(z.string().url()).min(1).max(10),
|
|
15
|
+
default_scopes: z.array(scopeSchema).min(1),
|
|
16
|
+
is_active: z.boolean().optional(),
|
|
17
|
+
confirm: z.literal(true).describe('Must be true after explicit user confirmation.'),
|
|
18
|
+
}),
|
|
19
|
+
|
|
20
|
+
async execute(
|
|
21
|
+
client: PosterlyClient,
|
|
22
|
+
input: {
|
|
23
|
+
client_name: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
homepage?: string;
|
|
26
|
+
allowed_redirect_uris: string[];
|
|
27
|
+
default_scopes: string[];
|
|
28
|
+
is_active?: boolean;
|
|
29
|
+
confirm: true;
|
|
30
|
+
},
|
|
31
|
+
) {
|
|
32
|
+
const { confirm: _confirm, ...payload } = input;
|
|
33
|
+
const result = await client.createOAuthClient(payload);
|
|
34
|
+
return `OAuth client created: ${result.client.client_name}\nclient_id: ${result.client.client_id}\nRedirect URIs: ${result.client.allowed_redirect_uris.join(', ')}`;
|
|
35
|
+
},
|
|
36
|
+
};
|