posterly-mcp-server 0.45.3 → 0.47.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.
Files changed (45) hide show
  1. package/README.md +6 -4
  2. package/dist/lib/api-client.d.ts +29 -2
  3. package/dist/lib/api-client.js +18 -4
  4. package/dist/lib/version.d.ts +1 -1
  5. package/dist/lib/version.js +1 -1
  6. package/dist/tools/create-media-drop.d.ts +4 -0
  7. package/dist/tools/create-media-drop.js +2 -0
  8. package/dist/tools/create-post.d.ts +6 -6
  9. package/dist/tools/create-posts-batch.d.ts +4 -4
  10. package/dist/tools/create-signed-upload.d.ts +4 -0
  11. package/dist/tools/create-signed-upload.js +2 -1
  12. package/dist/tools/delete-post.d.ts +4 -0
  13. package/dist/tools/delete-post.js +10 -5
  14. package/dist/tools/generate-image.d.ts +4 -0
  15. package/dist/tools/generate-image.js +1 -0
  16. package/dist/tools/generate-video.d.ts +3 -0
  17. package/dist/tools/generate-video.js +1 -0
  18. package/dist/tools/list-analytics.js +4 -1
  19. package/dist/tools/list-posts.d.ts +4 -0
  20. package/dist/tools/list-posts.js +5 -1
  21. package/dist/tools/list-workspace-members.d.ts +10 -0
  22. package/dist/tools/list-workspace-members.js +20 -2
  23. package/dist/tools/manage-workspace-member.d.ts +4 -0
  24. package/dist/tools/manage-workspace-member.js +17 -4
  25. package/dist/tools/update-post.d.ts +14 -2
  26. package/dist/tools/update-post.js +27 -1
  27. package/dist/tools/upload-media.d.ts +4 -0
  28. package/dist/tools/upload-media.js +3 -0
  29. package/dist/tools/validate-post.d.ts +4 -4
  30. package/package.json +1 -1
  31. package/server.json +2 -2
  32. package/src/lib/api-client.ts +43 -3
  33. package/src/lib/version.ts +1 -1
  34. package/src/tools/create-media-drop.ts +3 -1
  35. package/src/tools/create-signed-upload.ts +3 -2
  36. package/src/tools/delete-post.ts +16 -7
  37. package/src/tools/generate-image.ts +2 -0
  38. package/src/tools/generate-video.ts +1 -0
  39. package/src/tools/list-analytics.ts +4 -1
  40. package/src/tools/list-posts.ts +6 -1
  41. package/src/tools/list-workspace-members.ts +16 -2
  42. package/src/tools/manage-workspace-member.ts +16 -4
  43. package/src/tools/update-post.ts +46 -1
  44. package/src/tools/upload-media.ts +7 -2
  45. package/tool-registry.json +46 -0
package/README.md CHANGED
@@ -35,6 +35,7 @@ name is `io.github.awpthorp/posterly`, matching this package's `mcpName`.
35
35
  - Node.js `20+`
36
36
  - No API key is required for the public setup tools: `whoami` with `view: "status"`, `get_agent_signup_info`, `start_signup`, and `get_signup_session`
37
37
  - A posterly account, API add-on, and API key are required for authenticated tools like `whoami`, `list_accounts`, `create_connect_session`, and `create_post`
38
+ - A teammate does not need their own add-on when the workspace owner turned on **API and AI access** for them in Team settings: their key then works in that workspace, billed to the owner's plan ([Teammates and API access](https://www.poster.ly/docs/integrations/api#teammates-and-api-access))
38
39
 
39
40
  ## Install
40
41
 
@@ -122,7 +123,7 @@ Add the same server definition to your Cursor MCP settings:
122
123
 
123
124
  ## Available tools
124
125
 
125
- `posterly-mcp-server@0.45.3` exposes 62 tools covering 94 actions. The hosted HTTP endpoint exposes the same catalog minus the three signup tools: 59 tools covering 91 actions.
126
+ `posterly-mcp-server@0.47.0` exposes 62 tools covering 95 actions. The hosted HTTP endpoint exposes the same catalog minus the three signup tools: 59 tools covering 92 actions.
126
127
 
127
128
  Many tools pick what to do with one parameter: `view` (reads), `action` (writes), or `type`. A few pick their mode from which parameters you pass (for example `update_post` with `status` changes the status instead of editing). Every tool description names all of its views and actions.
128
129
 
@@ -210,13 +211,14 @@ Accounts, posting, media, schedule, analytics, and support. What most assistants
210
211
  | `edit` (default) | Edit caption, media, schedule, or settings |
211
212
  | `status` (pass `status`) | Pause, resume, schedule, or move to draft |
212
213
  | `release_id` (pass `release_id`) | Set a release or group ID |
214
+ | `approval` (pass `approval_action`) | Request, approve, request changes, or reject client review (owner or admin only) |
213
215
 
214
216
  **`delete_post`**: Delete posts
215
217
 
216
218
  | Mode (picked by params) | What it does |
217
219
  | --- | --- |
218
- | `post` (default) | Delete one post |
219
- | `group` (pass `group_id`) | Delete a post group (preview then confirm) |
220
+ | `post` (default) | Delete one post. Published Instagram or Facebook posts also need `confirm_published` |
221
+ | `group` (pass `group_id`) | Delete a post group (preview then confirm). Never deletes published posts |
220
222
 
221
223
  **`upload_media`**: Upload media
222
224
 
@@ -335,7 +337,7 @@ API keys, OAuth clients, webhooks, and workspace members.
335
337
  | Action | What it does |
336
338
  | --- | --- |
337
339
  | `invite` | Invite a colleague (preview then confirm) |
338
- | `update` | Change role or brands (preview then confirm) |
340
+ | `update` | Change role or brands, or turn a teammate's API and AI access on or off (preview then confirm) |
339
341
  | `remove` | Remove a member or invite (preview then confirm) |
340
342
 
341
343
  **`manage_oauth_client`**: Manage an OAuth client
@@ -145,6 +145,7 @@ export interface ApiPostApproval {
145
145
  asset_status: ApiPostApprovalStatus;
146
146
  caption_status: ApiPostApprovalStatus;
147
147
  waiting_on: 'client' | 'team' | null;
148
+ pending_client_approval: boolean;
148
149
  requested_at: string | null;
149
150
  completed_at: string | null;
150
151
  }
@@ -341,6 +342,14 @@ export type WorkspaceMemberSummary = {
341
342
  status: string | null;
342
343
  /** [] = every brand; missing = not visible to a brand-limited caller. */
343
344
  brand_ids?: string[];
345
+ /** Can this teammate use the workspace's API and AI app access. Always true for the owner. */
346
+ api_access?: boolean;
347
+ /** Owners and admins only: live keys and AI app connections for this workspace. */
348
+ api_usage?: {
349
+ key_count: number;
350
+ last_used_at: string | null;
351
+ connected_apps: string[];
352
+ };
344
353
  joined_at: string | null;
345
354
  created_at: string | null;
346
355
  };
@@ -375,6 +384,9 @@ export type WorkspaceMemberPreview = {
375
384
  counts_toward_seats: boolean;
376
385
  seats_used: number | null;
377
386
  seat_limit: number | null;
387
+ /** action=set_api_access only. */
388
+ api_access?: boolean;
389
+ previous_api_access?: boolean | null;
378
390
  };
379
391
  export type WorkspaceMemberChangeResponse = {
380
392
  requires_confirmation?: boolean;
@@ -1097,6 +1109,7 @@ export declare class PosterlyClient {
1097
1109
  }, data: {
1098
1110
  role?: WorkspaceMemberRole;
1099
1111
  brand_ids?: string[];
1112
+ api_access?: boolean;
1100
1113
  } & WorkspaceMemberConfirmFields): Promise<WorkspaceMemberChangeResponse>;
1101
1114
  removeWorkspaceMember(workspaceId: string, target: {
1102
1115
  member_id?: string;
@@ -1200,6 +1213,7 @@ export declare class PosterlyClient {
1200
1213
  offset?: number;
1201
1214
  workspace_id?: string;
1202
1215
  approval_status?: string;
1216
+ approval_waiting_on?: string;
1203
1217
  brand_id?: string;
1204
1218
  }): Promise<{
1205
1219
  posts: Post[];
@@ -1232,10 +1246,18 @@ export declare class PosterlyClient {
1232
1246
  }): Promise<{
1233
1247
  post: Post;
1234
1248
  }>;
1235
- deletePost(id: number): Promise<{
1249
+ deletePost(id: number, options?: {
1250
+ confirmPublished?: boolean;
1251
+ }): Promise<{
1236
1252
  deleted: boolean;
1237
1253
  id: number;
1254
+ platform_delete?: string;
1238
1255
  }>;
1256
+ setPostApproval(id: number, data: {
1257
+ action: 'request' | 'approve' | 'request_changes' | 'reject';
1258
+ axis?: 'asset' | 'caption';
1259
+ note?: string;
1260
+ }): Promise<Record<string, unknown>>;
1239
1261
  updatePostStatus(id: number, data: {
1240
1262
  status: 'scheduled' | 'paused' | 'draft';
1241
1263
  scheduled_at?: string;
@@ -1256,6 +1278,7 @@ export declare class PosterlyClient {
1256
1278
  quality?: 'low' | 'medium' | 'high';
1257
1279
  thinking_level?: 'minimal' | 'high';
1258
1280
  reference_image_urls?: string[];
1281
+ workspace_id?: string;
1259
1282
  }): Promise<{
1260
1283
  job_id: string;
1261
1284
  status: string;
@@ -1295,6 +1318,7 @@ export declare class PosterlyClient {
1295
1318
  }>;
1296
1319
  generate_audio?: boolean;
1297
1320
  source_video_url?: string;
1321
+ workspace_id?: string;
1298
1322
  }): Promise<Record<string, any>>;
1299
1323
  getVideoJob(params?: {
1300
1324
  job_id?: string;
@@ -1458,7 +1482,7 @@ export declare class PosterlyClient {
1458
1482
  getXPostingQuota(params?: {
1459
1483
  workspace_id?: string;
1460
1484
  }): Promise<XPostingQuotaResponse>;
1461
- getSignedUploadUrl(filename: string, contentType: string, size: number): Promise<{
1485
+ getSignedUploadUrl(filename: string, contentType: string, size: number, workspaceId?: string): Promise<{
1462
1486
  upload_url: string;
1463
1487
  token: string;
1464
1488
  path: string;
@@ -1468,6 +1492,7 @@ export declare class PosterlyClient {
1468
1492
  createMediaDrop(input?: {
1469
1493
  filename?: string;
1470
1494
  maxFiles?: number;
1495
+ workspaceId?: string;
1471
1496
  }): Promise<{
1472
1497
  session_id: string;
1473
1498
  drop_url: string;
@@ -1497,6 +1522,7 @@ export declare class PosterlyClient {
1497
1522
  base64Data?: string;
1498
1523
  filename: string;
1499
1524
  contentType?: string;
1525
+ workspaceId?: string;
1500
1526
  }): Promise<{
1501
1527
  url: string;
1502
1528
  path: string;
@@ -1505,6 +1531,7 @@ export declare class PosterlyClient {
1505
1531
  url: string;
1506
1532
  filename?: string;
1507
1533
  contentType?: string;
1534
+ workspaceId?: string;
1508
1535
  }): Promise<{
1509
1536
  url: string;
1510
1537
  path: string;
@@ -340,6 +340,8 @@ export class PosterlyClient {
340
340
  searchParams.set('workspace_id', params.workspace_id);
341
341
  if (params?.approval_status)
342
342
  searchParams.set('approval_status', params.approval_status);
343
+ if (params?.approval_waiting_on)
344
+ searchParams.set('approval_waiting_on', params.approval_waiting_on);
343
345
  if (params?.brand_id)
344
346
  searchParams.set('brand_id', params.brand_id);
345
347
  const qs = searchParams.toString();
@@ -375,8 +377,16 @@ export class PosterlyClient {
375
377
  async updatePost(id, data) {
376
378
  return this.request('PATCH', `/posts/${id}`, data);
377
379
  }
378
- async deletePost(id) {
379
- return this.request('DELETE', `/posts/${id}`);
380
+ async deletePost(id, options) {
381
+ const qs = options?.confirmPublished ? '?confirm_published=true' : '';
382
+ return this.request('DELETE', `/posts/${id}${qs}`);
383
+ }
384
+ async setPostApproval(id, data) {
385
+ return this.request('POST', `/posts/${id}/approval`, {
386
+ action: data.action,
387
+ ...(data.axis ? { axis: data.axis } : {}),
388
+ ...(data.note ? { note: data.note } : {}),
389
+ });
380
390
  }
381
391
  async updatePostStatus(id, data) {
382
392
  return this.request('PUT', `/posts/${id}/status`, data);
@@ -597,17 +607,19 @@ export class PosterlyClient {
597
607
  const qs = searchParams.toString();
598
608
  return this.request('GET', `/x-posting/quota${qs ? `?${qs}` : ''}`);
599
609
  }
600
- async getSignedUploadUrl(filename, contentType, size) {
610
+ async getSignedUploadUrl(filename, contentType, size, workspaceId) {
601
611
  return this.request('POST', '/media/signed-upload', {
602
612
  filename,
603
613
  content_type: contentType,
604
614
  size,
615
+ ...(workspaceId ? { workspace_id: workspaceId } : {}),
605
616
  });
606
617
  }
607
618
  async createMediaDrop(input) {
608
619
  return this.request('POST', '/media/drop-sessions', {
609
620
  filename: input?.filename,
610
621
  max_files: input?.maxFiles,
622
+ ...(input?.workspaceId ? { workspace_id: input.workspaceId } : {}),
611
623
  });
612
624
  }
613
625
  async listMedia(params) {
@@ -636,7 +648,7 @@ export class PosterlyClient {
636
648
  const SIZE_THRESHOLD = 3 * 1024 * 1024; // 3MB
637
649
  if (fileBuffer.length > SIZE_THRESHOLD) {
638
650
  // Large file: PUT to the object-storage signed URL (not a Vercel relay).
639
- const signed = await this.getSignedUploadUrl(input.filename, contentType, fileBuffer.length);
651
+ const signed = await this.getSignedUploadUrl(input.filename, contentType, fileBuffer.length, input.workspaceId);
640
652
  const uploadRes = await fetch(signed.upload_url, {
641
653
  method: 'PUT',
642
654
  headers: {
@@ -657,6 +669,7 @@ export class PosterlyClient {
657
669
  filename: input.filename,
658
670
  data,
659
671
  content_type: contentType,
672
+ ...(input.workspaceId ? { workspace_id: input.workspaceId } : {}),
660
673
  });
661
674
  }
662
675
  async uploadMediaFromUrl(input) {
@@ -664,6 +677,7 @@ export class PosterlyClient {
664
677
  url: input.url,
665
678
  filename: input.filename,
666
679
  content_type: input.contentType,
680
+ ...(input.workspaceId ? { workspace_id: input.workspaceId } : {}),
667
681
  });
668
682
  }
669
683
  appendInboxListParams(searchParams, params) {
@@ -1 +1 @@
1
- export declare const POSTERLY_MCP_VERSION = "0.45.3";
1
+ export declare const POSTERLY_MCP_VERSION = "0.47.0";
@@ -5,4 +5,4 @@
5
5
  // tool set (minus the intentional pre-auth signup tools that only this stdio
6
6
  // package exposes). `npm run check:mcp-parity` enforces both the version match
7
7
  // and the tool-list match, and runs in the pre-commit hook.
8
- export const POSTERLY_MCP_VERSION = '0.45.3';
8
+ export const POSTERLY_MCP_VERSION = '0.47.0';
@@ -6,15 +6,19 @@ export declare const createMediaDropTool: {
6
6
  inputSchema: z.ZodObject<{
7
7
  filename: z.ZodOptional<z.ZodString>;
8
8
  max_files: z.ZodOptional<z.ZodNumber>;
9
+ workspace_id: z.ZodOptional<z.ZodString>;
9
10
  }, "strip", z.ZodTypeAny, {
11
+ workspace_id?: string | undefined;
10
12
  filename?: string | undefined;
11
13
  max_files?: number | undefined;
12
14
  }, {
15
+ workspace_id?: string | undefined;
13
16
  filename?: string | undefined;
14
17
  max_files?: number | undefined;
15
18
  }>;
16
19
  execute(client: PosterlyClient, input: {
17
20
  filename?: string;
18
21
  max_files?: number;
22
+ workspace_id?: string;
19
23
  }): Promise<string>;
20
24
  };
@@ -11,11 +11,13 @@ export const createMediaDropTool = {
11
11
  .max(10)
12
12
  .optional()
13
13
  .describe('How many files the drop can accept. Default 10, max 10.'),
14
+ workspace_id: z.string().optional().describe('Optional. The workspace this acts in and whose plan pays (from whoami). Needed only when your connection can act in several workspaces.'),
14
15
  }),
15
16
  async execute(client, input) {
16
17
  const drop = await client.createMediaDrop({
17
18
  filename: input.filename,
18
19
  maxFiles: input.max_files,
20
+ workspaceId: input.workspace_id,
19
21
  });
20
22
  return [
21
23
  'Media drop created. Send this URL to the user. They open it with no posterly login and drop the file.',
@@ -972,11 +972,11 @@ export declare const createPostPayloadInputSchema: z.ZodObject<{
972
972
  username?: string | undefined;
973
973
  workspace_id?: string | undefined;
974
974
  account_id?: string | undefined;
975
+ caption?: string | undefined;
975
976
  scheduled_at?: string | undefined;
976
977
  media_url?: string | undefined;
977
978
  media_urls?: string[] | undefined;
978
979
  post_type?: string | undefined;
979
- caption?: string | undefined;
980
980
  thread_posts?: string[] | undefined;
981
981
  instagram_settings?: {
982
982
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -1135,11 +1135,11 @@ export declare const createPostPayloadInputSchema: z.ZodObject<{
1135
1135
  username?: string | undefined;
1136
1136
  workspace_id?: string | undefined;
1137
1137
  account_id?: string | undefined;
1138
+ caption?: string | undefined;
1138
1139
  scheduled_at?: string | undefined;
1139
1140
  media_url?: string | undefined;
1140
1141
  media_urls?: string[] | undefined;
1141
1142
  post_type?: string | undefined;
1142
- caption?: string | undefined;
1143
1143
  thread_posts?: string[] | undefined;
1144
1144
  instagram_settings?: {
1145
1145
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -1791,11 +1791,11 @@ export declare const createPostInputSchema: z.ZodObject<{
1791
1791
  username?: string | undefined;
1792
1792
  workspace_id?: string | undefined;
1793
1793
  account_id?: string | undefined;
1794
+ caption?: string | undefined;
1794
1795
  scheduled_at?: string | undefined;
1795
1796
  media_url?: string | undefined;
1796
1797
  media_urls?: string[] | undefined;
1797
1798
  post_type?: string | undefined;
1798
- caption?: string | undefined;
1799
1799
  thread_posts?: string[] | undefined;
1800
1800
  instagram_settings?: {
1801
1801
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -1955,11 +1955,11 @@ export declare const createPostInputSchema: z.ZodObject<{
1955
1955
  username?: string | undefined;
1956
1956
  workspace_id?: string | undefined;
1957
1957
  account_id?: string | undefined;
1958
+ caption?: string | undefined;
1958
1959
  scheduled_at?: string | undefined;
1959
1960
  media_url?: string | undefined;
1960
1961
  media_urls?: string[] | undefined;
1961
1962
  post_type?: string | undefined;
1962
- caption?: string | undefined;
1963
1963
  thread_posts?: string[] | undefined;
1964
1964
  instagram_settings?: {
1965
1965
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -2640,11 +2640,11 @@ export declare const createPostTool: {
2640
2640
  username?: string | undefined;
2641
2641
  workspace_id?: string | undefined;
2642
2642
  account_id?: string | undefined;
2643
+ caption?: string | undefined;
2643
2644
  scheduled_at?: string | undefined;
2644
2645
  media_url?: string | undefined;
2645
2646
  media_urls?: string[] | undefined;
2646
2647
  post_type?: string | undefined;
2647
- caption?: string | undefined;
2648
2648
  thread_posts?: string[] | undefined;
2649
2649
  instagram_settings?: {
2650
2650
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -2804,11 +2804,11 @@ export declare const createPostTool: {
2804
2804
  username?: string | undefined;
2805
2805
  workspace_id?: string | undefined;
2806
2806
  account_id?: string | undefined;
2807
+ caption?: string | undefined;
2807
2808
  scheduled_at?: string | undefined;
2808
2809
  media_url?: string | undefined;
2809
2810
  media_urls?: string[] | undefined;
2810
2811
  post_type?: string | undefined;
2811
- caption?: string | undefined;
2812
2812
  thread_posts?: string[] | undefined;
2813
2813
  instagram_settings?: {
2814
2814
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -499,11 +499,11 @@ export declare const createPostsBatchTool: {
499
499
  username?: string | undefined;
500
500
  workspace_id?: string | undefined;
501
501
  account_id?: string | undefined;
502
+ caption?: string | undefined;
502
503
  scheduled_at?: string | undefined;
503
504
  media_url?: string | undefined;
504
505
  media_urls?: string[] | undefined;
505
506
  post_type?: string | undefined;
506
- caption?: string | undefined;
507
507
  thread_posts?: string[] | undefined;
508
508
  instagram_settings?: {
509
509
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -662,11 +662,11 @@ export declare const createPostsBatchTool: {
662
662
  username?: string | undefined;
663
663
  workspace_id?: string | undefined;
664
664
  account_id?: string | undefined;
665
+ caption?: string | undefined;
665
666
  scheduled_at?: string | undefined;
666
667
  media_url?: string | undefined;
667
668
  media_urls?: string[] | undefined;
668
669
  post_type?: string | undefined;
669
- caption?: string | undefined;
670
670
  thread_posts?: string[] | undefined;
671
671
  instagram_settings?: {
672
672
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -829,11 +829,11 @@ export declare const createPostsBatchTool: {
829
829
  username?: string | undefined;
830
830
  workspace_id?: string | undefined;
831
831
  account_id?: string | undefined;
832
+ caption?: string | undefined;
832
833
  scheduled_at?: string | undefined;
833
834
  media_url?: string | undefined;
834
835
  media_urls?: string[] | undefined;
835
836
  post_type?: string | undefined;
836
- caption?: string | undefined;
837
837
  thread_posts?: string[] | undefined;
838
838
  instagram_settings?: {
839
839
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -995,11 +995,11 @@ export declare const createPostsBatchTool: {
995
995
  username?: string | undefined;
996
996
  workspace_id?: string | undefined;
997
997
  account_id?: string | undefined;
998
+ caption?: string | undefined;
998
999
  scheduled_at?: string | undefined;
999
1000
  media_url?: string | undefined;
1000
1001
  media_urls?: string[] | undefined;
1001
1002
  post_type?: string | undefined;
1002
- caption?: string | undefined;
1003
1003
  thread_posts?: string[] | undefined;
1004
1004
  instagram_settings?: {
1005
1005
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
@@ -7,18 +7,22 @@ export declare const createSignedUploadTool: {
7
7
  filename: z.ZodString;
8
8
  content_type: z.ZodString;
9
9
  size: z.ZodNumber;
10
+ workspace_id: z.ZodOptional<z.ZodString>;
10
11
  }, "strip", z.ZodTypeAny, {
11
12
  filename: string;
12
13
  content_type: string;
13
14
  size: number;
15
+ workspace_id?: string | undefined;
14
16
  }, {
15
17
  filename: string;
16
18
  content_type: string;
17
19
  size: number;
20
+ workspace_id?: string | undefined;
18
21
  }>;
19
22
  execute(client: PosterlyClient, input: {
20
23
  filename: string;
21
24
  content_type: string;
22
25
  size: number;
26
+ workspace_id?: string;
23
27
  }): Promise<string>;
24
28
  };
@@ -6,9 +6,10 @@ export const createSignedUploadTool = {
6
6
  filename: z.string().describe('Filename with extension, e.g. launch-video.mp4'),
7
7
  content_type: z.string().describe('MIME type, e.g. video/mp4'),
8
8
  size: z.number().int().positive().describe('File size in bytes'),
9
+ workspace_id: z.string().optional().describe('Optional. The workspace this acts in and whose plan pays (from whoami). Needed only when your connection can act in several workspaces.'),
9
10
  }),
10
11
  async execute(client, input) {
11
- const signed = await client.getSignedUploadUrl(input.filename, input.content_type, input.size);
12
+ const signed = await client.getSignedUploadUrl(input.filename, input.content_type, input.size, input.workspace_id);
12
13
  return [
13
14
  'Signed upload created.',
14
15
  `• Upload URL: ${signed.upload_url}`,
@@ -4,6 +4,7 @@ import { type ToolContext } from '../lib/tool-runtime.js';
4
4
  type DeletePostInput = {
5
5
  post_id?: number;
6
6
  group_id?: string;
7
+ confirm_published?: boolean;
7
8
  confirm?: boolean;
8
9
  preview_id?: string;
9
10
  };
@@ -13,6 +14,7 @@ export declare const deletePostTool: {
13
14
  inputSchema: z.ZodObject<{
14
15
  post_id: z.ZodOptional<z.ZodNumber>;
15
16
  group_id: z.ZodOptional<z.ZodString>;
17
+ confirm_published: z.ZodOptional<z.ZodBoolean>;
16
18
  confirm: z.ZodOptional<z.ZodBoolean>;
17
19
  preview_id: z.ZodOptional<z.ZodString>;
18
20
  }, "strip", z.ZodTypeAny, {
@@ -20,11 +22,13 @@ export declare const deletePostTool: {
20
22
  preview_id?: string | undefined;
21
23
  post_id?: number | undefined;
22
24
  group_id?: string | undefined;
25
+ confirm_published?: boolean | undefined;
23
26
  }, {
24
27
  confirm?: boolean | undefined;
25
28
  preview_id?: string | undefined;
26
29
  post_id?: number | undefined;
27
30
  group_id?: string | undefined;
31
+ confirm_published?: boolean | undefined;
28
32
  }>;
29
33
  /** The old tools' exact input schemas, for alias calls (see alias-transport.ts). */
30
34
  legacySchemas: {
@@ -3,10 +3,14 @@ import { code, dashboardUrlForPosts } from '../lib/format.js';
3
3
  import { previewThenConfirm, validateArgs } from '../lib/tool-runtime.js';
4
4
  export const deletePostTool = {
5
5
  name: 'delete_post',
6
- description: 'Delete posts. DESTRUCTIVE and IRREVERSIBLE: deleted posts and captions cannot be recovered, and published or currently publishing posts are never deleted. post_id: delete one scheduled or draft post; fetch it with `get_post` first, show the user what will be deleted (caption, account, scheduled time), and pass confirm=true only after explicit confirmation ("yes delete it", "remove it"). group_id: delete every draft, scheduled, failed, or paused post matching a caller-defined group_id, post_group_id, api_group_id, or release_id; preview then confirm: call without confirm to get a preview and preview_id, show it, then call again with confirm=true and that preview_id. Never delete several posts one by one without listing each and confirming the full list.',
6
+ description: 'Delete posts. DESTRUCTIVE and IRREVERSIBLE: deleted posts and captions cannot be recovered. post_id: delete one post; fetch it with `get_post` first, show the user what will be deleted (caption, account, scheduled time), and pass confirm=true only after explicit confirmation ("yes delete it", "remove it"). A post that is currently publishing is never deleted. A published post is taken down only when the user also explicitly confirms the live removal and you pass confirm_published=true. Instagram and Facebook are attempted when the stored id and token allow it. Every other platform, or a live URL with no id, returns platform_delete_unsupported and the posterly row is kept. A published post with no live URL and no platform id is removed from posterly only. group_id: delete every draft, scheduled, failed, or paused post matching a caller-defined group_id, post_group_id, api_group_id, or release_id. A group delete never removes published posts. Preview then confirm: call without confirm to get a preview and preview_id, show it, then call again with confirm=true and that preview_id. Never delete several posts one by one without listing each and confirming the full list.',
7
7
  inputSchema: z.object({
8
8
  post_id: z.number().optional().describe('Delete this one post.'),
9
- group_id: z.string().min(1).max(160).optional().describe('Delete every unpublished post in this group or release instead.'),
9
+ group_id: z.string().min(1).max(160).optional().describe('Delete every unpublished post in this group or release instead. Never deletes published posts.'),
10
+ confirm_published: z
11
+ .boolean()
12
+ .optional()
13
+ .describe('With post_id only. True only after the user explicitly confirms taking a live Instagram or Facebook post down. Without it, a published post is refused and kept.'),
10
14
  confirm: z
11
15
  .boolean()
12
16
  .optional()
@@ -33,7 +37,7 @@ export const deletePostTool = {
33
37
  // GET /api/v1/posts has no group filter, so the preview says in plain
34
38
  // words which posts match instead of listing them.
35
39
  describe: async () => [
36
- `Deletes every draft, scheduled, failed, or paused post whose group_id, post_group_id, api_group_id, or release_id is ${code(args.group_id)}. Published posts are never deleted. This cannot be undone.`,
40
+ `Deletes every draft, scheduled, failed, or paused post whose group_id, post_group_id, api_group_id, or release_id is ${code(args.group_id)}. A group delete never removes published posts. This cannot be undone.`,
37
41
  'To see the posts first, call list_posts and check each post\'s group or release ID.',
38
42
  ].join('\n\n'),
39
43
  run: async () => {
@@ -49,9 +53,10 @@ async function deleteOne(client, input) {
49
53
  if (input.confirm !== true) {
50
54
  throw new Error('Refusing to delete post without confirm=true after explicit user confirmation.');
51
55
  }
52
- const result = await client.deletePost(input.post_id);
56
+ const result = await client.deletePost(input.post_id, { confirmPublished: input.confirm_published === true });
57
+ const platformDelete = result.platform_delete ? ` Platform delete: ${result.platform_delete}.` : '';
53
58
  return [
54
- `Post #${result.id} deleted successfully.`,
59
+ `Post #${result.id} deleted successfully.${platformDelete}`,
55
60
  'It has been removed from the posterly queue.',
56
61
  `View queue in posterly: ${dashboardUrlForPosts()}`,
57
62
  '',
@@ -14,10 +14,12 @@ export declare const generateImageTool: {
14
14
  quality: z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>;
15
15
  thinking_level: z.ZodOptional<z.ZodEnum<["minimal", "high"]>>;
16
16
  reference_image_urls: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
17
+ workspace_id: z.ZodOptional<z.ZodString>;
17
18
  confirm: z.ZodLiteral<true>;
18
19
  }, "strip", z.ZodTypeAny, {
19
20
  confirm: true;
20
21
  prompt: string;
22
+ workspace_id?: string | undefined;
21
23
  provider?: "google" | "xai" | undefined;
22
24
  aspect_ratio?: "1:1" | "16:9" | "9:16" | "4:3" | "3:4" | "3:2" | "2:3" | "4:5" | "1:4" | "1:8" | "21:9" | "4:1" | "8:1" | "5:4" | undefined;
23
25
  resolution?: "512" | "1K" | "2K" | "4K" | undefined;
@@ -30,6 +32,7 @@ export declare const generateImageTool: {
30
32
  }, {
31
33
  confirm: true;
32
34
  prompt: string;
35
+ workspace_id?: string | undefined;
33
36
  provider?: "google" | "xai" | undefined;
34
37
  aspect_ratio?: "1:1" | "16:9" | "9:16" | "4:3" | "3:4" | "3:2" | "2:3" | "4:5" | "1:4" | "1:8" | "21:9" | "4:1" | "8:1" | "5:4" | undefined;
35
38
  resolution?: "512" | "1K" | "2K" | "4K" | undefined;
@@ -51,6 +54,7 @@ export declare const generateImageTool: {
51
54
  quality?: "low" | "medium" | "high";
52
55
  thinking_level?: "minimal" | "high";
53
56
  reference_image_urls?: string[];
57
+ workspace_id?: string;
54
58
  confirm: true;
55
59
  }): Promise<string>;
56
60
  };
@@ -62,6 +62,7 @@ export const generateImageTool = {
62
62
  .max(14)
63
63
  .optional()
64
64
  .describe('Google only. Up to 14 HTTPS image URLs used as references (logo, product, style lock). Same as dashboard reference images.'),
65
+ workspace_id: z.string().optional().describe('Optional. The workspace this acts in and whose plan pays (from whoami). Needed only when your connection can act in several workspaces.'),
65
66
  confirm: z.literal(true).describe('Must be true after explicit user confirmation of subject, style, aspect ratio, quality, and credit use.'),
66
67
  }),
67
68
  async execute(client, input) {
@@ -25,10 +25,12 @@ export declare const generateVideoTool: {
25
25
  }>, "many">>;
26
26
  generate_audio: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
27
27
  source_video_url: z.ZodOptional<z.ZodString>;
28
+ workspace_id: z.ZodOptional<z.ZodString>;
28
29
  confirm: z.ZodLiteral<true>;
29
30
  }, "strip", z.ZodTypeAny, {
30
31
  confirm: true;
31
32
  prompt: string;
33
+ workspace_id?: string | undefined;
32
34
  provider?: "google" | "xai" | undefined;
33
35
  negative_prompt?: string | undefined;
34
36
  aspect_ratio?: "1:1" | "16:9" | "9:16" | "4:3" | "3:4" | "3:2" | "2:3" | undefined;
@@ -46,6 +48,7 @@ export declare const generateVideoTool: {
46
48
  }, {
47
49
  confirm: true;
48
50
  prompt: string;
51
+ workspace_id?: string | undefined;
49
52
  provider?: "google" | "xai" | undefined;
50
53
  negative_prompt?: string | undefined;
51
54
  aspect_ratio?: "1:1" | "16:9" | "9:16" | "4:3" | "3:4" | "3:2" | "2:3" | undefined;
@@ -18,6 +18,7 @@ export const generateVideoTool = {
18
18
  })).max(3).optional(),
19
19
  generate_audio: z.boolean().default(true).optional().describe('Google can disable generated audio. xAI Grok includes audio and requires this to remain true.'),
20
20
  source_video_url: z.string().url().optional(),
21
+ workspace_id: z.string().optional().describe('Optional. The workspace this acts in and whose plan pays (from whoami). Needed only when your connection can act in several workspaces.'),
21
22
  confirm: z.literal(true).describe('Must be true after explicit user confirmation of prompt, model, duration, resolution, and credit cost.'),
22
23
  }),
23
24
  async execute(client, input) {
@@ -4,7 +4,7 @@ import { validateArgs } from '../lib/tool-runtime.js';
4
4
  const presentationSchema = z.enum(['compact', 'table', 'json']).optional();
5
5
  export const listAnalyticsTool = {
6
6
  name: 'list_analytics',
7
- description: 'Analytics for connected social accounts (Instagram, Facebook, LinkedIn, Google Business Profile, Pinterest, YouTube, and Threads). view=accounts (account_id): daily snapshots and a period summary with platform-native display_metrics labels. view=posts (account_id): per-post likes, comments/replies, reach, impressions/views, saves, shares, reposts, quotes, plays, clicks, and watch time, most recent first, with limit/offset. view=insights: per-post feedback insights with a performance tier (great/good/mixed/poor), diagnosis, next action, and baseline, filtered by account_id, post_id, or checkpoint (1h, 6h, 24h, 72h, 7d); read-only, Pro plan or higher. presentation (accounts and posts): compact for Telegram/mobile, table for Markdown clients, json for custom chart/card renderers.',
7
+ description: 'Analytics for connected social accounts (Instagram, Facebook, LinkedIn, Google Business Profile, Pinterest, YouTube, and Threads). view=accounts (account_id): daily snapshots and a period summary with platform-native display_metrics labels. Google Business Profile account analytics includes Calls, Website clicks, and Directions along with Profile Views, Search Views, Maps Views, Customer Actions, and Posts. view=posts (account_id): per-post likes, comments/replies, reach, impressions/views, saves, shares, reposts, quotes, plays, clicks, and watch time, most recent first, with limit/offset. view=insights: per-post feedback insights with a performance tier (great/good/mixed/poor), diagnosis, next action, and baseline, filtered by account_id, post_id, or checkpoint (1h, 6h, 24h, 72h, 7d); read-only, Pro plan or higher. presentation (accounts and posts): compact for Telegram/mobile, table for Markdown clients, json for custom chart/card renderers.',
8
8
  inputSchema: z.object({
9
9
  view: z.enum(['accounts', 'posts', 'insights']).describe('accounts, posts, or insights.'),
10
10
  account_id: z
@@ -150,6 +150,9 @@ function accountMetricRows(summary, platform) {
150
150
  ['Search Views', formatNumber(metrics.search_views ?? summary.total_reach)],
151
151
  ['Maps Views', formatNumber(metrics.maps_views ?? summary.total_profile_views)],
152
152
  ['Customer Actions', formatNumber(metrics.customer_actions ?? summary.total_accounts_engaged)],
153
+ ['Calls', formatNumber(metrics.call_clicks ?? summary.total_call_clicks)],
154
+ ['Directions', formatNumber(metrics.direction_requests ?? summary.total_direction_requests)],
155
+ ['Website clicks', formatNumber(metrics.website_clicks ?? summary.total_website_clicks)],
153
156
  ['Posts', formatNumber(metrics.posts ?? summary.current_media_count)],
154
157
  ];
155
158
  }
@@ -10,6 +10,7 @@ export declare const listPostsTool: {
10
10
  limit: z.ZodOptional<z.ZodNumber>;
11
11
  workspace_id: z.ZodOptional<z.ZodString>;
12
12
  approval_status: z.ZodOptional<z.ZodEnum<["none", "pending_client", "approved", "changes_requested", "rejected"]>>;
13
+ approval_waiting_on: z.ZodOptional<z.ZodEnum<["client", "team"]>>;
13
14
  brand_id: z.ZodOptional<z.ZodString>;
14
15
  }, "strip", z.ZodTypeAny, {
15
16
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "threads" | "linkedin" | "youtube" | "pinterest" | "google_business" | "x" | "telegram" | "bluesky" | "discord" | "wordpress" | "devto" | "hashnode" | "lemmy" | "slack" | "mastodon" | "gmb" | "google-business" | "google_business_profile" | undefined;
@@ -18,6 +19,7 @@ export declare const listPostsTool: {
18
19
  account_id?: string | undefined;
19
20
  limit?: number | undefined;
20
21
  approval_status?: "none" | "pending_client" | "approved" | "changes_requested" | "rejected" | undefined;
22
+ approval_waiting_on?: "client" | "team" | undefined;
21
23
  brand_id?: string | undefined;
22
24
  }, {
23
25
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "threads" | "linkedin" | "youtube" | "pinterest" | "google_business" | "x" | "telegram" | "bluesky" | "discord" | "wordpress" | "devto" | "hashnode" | "lemmy" | "slack" | "mastodon" | "gmb" | "google-business" | "google_business_profile" | undefined;
@@ -26,6 +28,7 @@ export declare const listPostsTool: {
26
28
  account_id?: string | undefined;
27
29
  limit?: number | undefined;
28
30
  approval_status?: "none" | "pending_client" | "approved" | "changes_requested" | "rejected" | undefined;
31
+ approval_waiting_on?: "client" | "team" | undefined;
29
32
  brand_id?: string | undefined;
30
33
  }>;
31
34
  execute(client: PosterlyClient, input: {
@@ -35,6 +38,7 @@ export declare const listPostsTool: {
35
38
  limit?: number;
36
39
  workspace_id?: string;
37
40
  approval_status?: string;
41
+ approval_waiting_on?: "client" | "team";
38
42
  brand_id?: string;
39
43
  }): Promise<string>;
40
44
  };