posterly-mcp-server 0.19.6 → 0.19.7

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 (37) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/lib/format.d.ts +11 -0
  4. package/dist/lib/format.js +51 -0
  5. package/dist/tools/create-connect-session.d.ts +4 -0
  6. package/dist/tools/create-connect-session.js +17 -8
  7. package/dist/tools/create-post.d.ts +39 -39
  8. package/dist/tools/create-post.js +8 -4
  9. package/dist/tools/create-posts-batch.d.ts +29 -29
  10. package/dist/tools/create-posts-batch.js +7 -1
  11. package/dist/tools/delete-post.js +8 -1
  12. package/dist/tools/get-agent-signup-info.js +5 -0
  13. package/dist/tools/get-connect-link.d.ts +4 -0
  14. package/dist/tools/get-connect-link.js +7 -2
  15. package/dist/tools/get-connect-session.d.ts +4 -0
  16. package/dist/tools/get-connect-session.js +33 -5
  17. package/dist/tools/get-post.js +3 -1
  18. package/dist/tools/get-signup-session.d.ts +4 -0
  19. package/dist/tools/get-signup-session.js +8 -5
  20. package/dist/tools/list-posts.js +11 -4
  21. package/dist/tools/start-signup.d.ts +4 -0
  22. package/dist/tools/start-signup.js +8 -5
  23. package/dist/tools/update-post.d.ts +20 -20
  24. package/package.json +1 -1
  25. package/src/index.ts +1 -1
  26. package/src/lib/format.ts +56 -0
  27. package/src/tools/create-connect-session.ts +18 -9
  28. package/src/tools/create-post.ts +11 -4
  29. package/src/tools/create-posts-batch.ts +11 -1
  30. package/src/tools/delete-post.ts +8 -1
  31. package/src/tools/get-agent-signup-info.ts +5 -0
  32. package/src/tools/get-connect-link.ts +8 -3
  33. package/src/tools/get-connect-session.ts +35 -6
  34. package/src/tools/get-post.ts +3 -1
  35. package/src/tools/get-signup-session.ts +9 -6
  36. package/src/tools/list-posts.ts +11 -5
  37. package/src/tools/start-signup.ts +9 -5
package/README.md CHANGED
@@ -103,7 +103,7 @@ Add the same server definition to your Cursor MCP settings:
103
103
 
104
104
  ## Available tools
105
105
 
106
- `posterly-mcp-server@0.19.6` exposes 54 tools.
106
+ `posterly-mcp-server@0.19.7` exposes 54 tools.
107
107
 
108
108
  Public signup tools work before `POSTERLY_API_KEY` exists:
109
109
 
package/dist/index.js CHANGED
@@ -58,7 +58,7 @@ import { updateOAuthClientTool } from './tools/update-oauth-client.js';
58
58
  import { deleteOAuthClientTool } from './tools/delete-oauth-client.js';
59
59
  const server = new McpServer({
60
60
  name: 'posterly',
61
- version: '0.19.6',
61
+ version: '0.19.7',
62
62
  });
63
63
  const client = new PosterlyClient();
64
64
  // Register tools
@@ -0,0 +1,11 @@
1
+ import type { Account, Post } from './api-client.js';
2
+ export declare const DASHBOARD_CALENDAR_URL: string;
3
+ export declare const DASHBOARD_TABLE_URL: string;
4
+ export declare const DASHBOARD_CONNECT_URL: string;
5
+ export declare function formatLocalDateTime(value?: string | null): string;
6
+ export declare function dashboardUrlForPost(post: Pick<Post, 'id' | 'scheduled_at'>): string;
7
+ export declare function dashboardUrlForPosts(): string;
8
+ export declare function dashboardUrlForPostList(posts: Array<Pick<Post, 'scheduled_at'>>): string;
9
+ export declare function truncateText(value: string | null | undefined, max?: number): string;
10
+ export declare function formatAccountLabel(account: Account): string;
11
+ export declare function formatConnectedAccounts(accounts?: Account[]): string;
@@ -0,0 +1,51 @@
1
+ const POSTERLY_APP_URL = (process.env.POSTERLY_URL || 'https://www.poster.ly').replace(/\/$/, '');
2
+ export const DASHBOARD_CALENDAR_URL = `${POSTERLY_APP_URL}/dashboard/calendar`;
3
+ export const DASHBOARD_TABLE_URL = `${POSTERLY_APP_URL}/dashboard/table`;
4
+ export const DASHBOARD_CONNECT_URL = `${POSTERLY_APP_URL}/dashboard/connect`;
5
+ export function formatLocalDateTime(value) {
6
+ if (!value)
7
+ return 'N/A';
8
+ const date = new Date(value);
9
+ if (Number.isNaN(date.getTime()))
10
+ return value;
11
+ return date.toLocaleString();
12
+ }
13
+ export function dashboardUrlForPost(post) {
14
+ const baseUrl = isInCurrentMonth(post.scheduled_at) ? DASHBOARD_CALENDAR_URL : DASHBOARD_TABLE_URL;
15
+ const url = new URL(baseUrl);
16
+ url.searchParams.set('post_id', String(post.id));
17
+ return url.toString();
18
+ }
19
+ export function dashboardUrlForPosts() {
20
+ return DASHBOARD_TABLE_URL;
21
+ }
22
+ export function dashboardUrlForPostList(posts) {
23
+ if (posts.length > 0 && posts.every((post) => isInCurrentMonth(post.scheduled_at))) {
24
+ return DASHBOARD_CALENDAR_URL;
25
+ }
26
+ return DASHBOARD_TABLE_URL;
27
+ }
28
+ export function truncateText(value, max = 80) {
29
+ const text = value?.trim() || '';
30
+ if (!text)
31
+ return '(empty)';
32
+ return text.length > max ? `${text.slice(0, max - 1)}...` : text;
33
+ }
34
+ export function formatAccountLabel(account) {
35
+ const username = account.username ? `@${account.username}` : `account ${account.id}`;
36
+ return `${account.platform} ${username}`;
37
+ }
38
+ export function formatConnectedAccounts(accounts) {
39
+ if (!accounts?.length)
40
+ return 'none yet';
41
+ return accounts.map(formatAccountLabel).join(', ');
42
+ }
43
+ function isInCurrentMonth(value) {
44
+ if (!value)
45
+ return false;
46
+ const date = new Date(value);
47
+ if (Number.isNaN(date.getTime()))
48
+ return false;
49
+ const now = new Date();
50
+ return date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth();
51
+ }
@@ -7,18 +7,22 @@ export declare const createConnectSessionTool: {
7
7
  platform: z.ZodEnum<["bluesky", "devto", "discord", "facebook", "facebook_instagram", "facebook_pages", "gmb", "google-business", "google_business", "google_business_profile", "hashnode", "instagram", "instagram-standalone", "instagram_direct", "linkedin", "linkedin-company", "linkedin-page", "linkedin_company", "linkedin_page", "linkedin_personal", "mastodon", "medium", "meta", "meta_business", "pinterest", "reddit", "skool", "slack", "telegram", "threads", "tiktok", "twitter", "whop", "wordpress", "x", "x_twitter", "youtube"]>;
8
8
  workspace_id: z.ZodOptional<z.ZodString>;
9
9
  auto_start: z.ZodOptional<z.ZodBoolean>;
10
+ debug: z.ZodOptional<z.ZodBoolean>;
10
11
  }, "strip", z.ZodTypeAny, {
11
12
  platform: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "reddit" | "wordpress" | "mastodon" | "medium" | "devto" | "hashnode" | "discord" | "slack" | "skool" | "whop" | "gmb" | "google-business" | "google_business_profile" | "x" | "meta" | "linkedin_page" | "facebook_instagram" | "facebook_pages" | "instagram_direct" | "linkedin-company" | "linkedin-page" | "linkedin_company" | "linkedin_personal" | "meta_business" | "x_twitter";
12
13
  workspace_id?: string | undefined;
13
14
  auto_start?: boolean | undefined;
15
+ debug?: boolean | undefined;
14
16
  }, {
15
17
  platform: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "reddit" | "wordpress" | "mastodon" | "medium" | "devto" | "hashnode" | "discord" | "slack" | "skool" | "whop" | "gmb" | "google-business" | "google_business_profile" | "x" | "meta" | "linkedin_page" | "facebook_instagram" | "facebook_pages" | "instagram_direct" | "linkedin-company" | "linkedin-page" | "linkedin_company" | "linkedin_personal" | "meta_business" | "x_twitter";
16
18
  workspace_id?: string | undefined;
17
19
  auto_start?: boolean | undefined;
20
+ debug?: boolean | undefined;
18
21
  }>;
19
22
  execute(client: PosterlyClient, input: {
20
23
  platform: string;
21
24
  workspace_id?: string;
22
25
  auto_start?: boolean;
26
+ debug?: boolean;
23
27
  }): Promise<string>;
24
28
  };
@@ -1,8 +1,9 @@
1
1
  import { z } from 'zod';
2
+ import { DASHBOARD_CONNECT_URL, formatConnectedAccounts, formatLocalDateTime } from '../lib/format.js';
2
3
  import { CONNECT_INPUTS } from '../generated/platform-manifest.js';
3
4
  export const createConnectSessionTool = {
4
5
  name: 'create_connect_session',
5
- description: 'Create a short-lived Posterly dashboard handoff session for connecting a social account. Open connect_session.connect_url for the user, then poll get_connect_session to narrate progress.',
6
+ description: 'Create a short-lived Posterly dashboard handoff session for connecting a social account. Send the secure connection URL to the user, then poll get_connect_session to narrate progress. Do not ask for social media passwords or OAuth codes; Posterly handles those browser steps.',
6
7
  inputSchema: z.object({
7
8
  platform: z
8
9
  .enum(CONNECT_INPUTS)
@@ -15,24 +16,32 @@ export const createConnectSessionTool = {
15
16
  .boolean()
16
17
  .optional()
17
18
  .describe('When true, the dashboard starts the provider flow after the user opens the URL. Defaults to true.'),
19
+ debug: z
20
+ .boolean()
21
+ .optional()
22
+ .describe('When true, include the raw connect session JSON for debugging. Keep false for normal user-facing agent flows.'),
18
23
  }),
19
24
  async execute(client, input) {
20
- const result = await client.createConnectSession(input);
21
- return formatConnectSession(result.connect_session, true);
25
+ const { debug, ...payload } = input;
26
+ const result = await client.createConnectSession(payload);
27
+ return formatConnectSession(result.connect_session, Boolean(debug));
22
28
  },
23
29
  };
24
30
  function formatConnectSession(session, includeRaw) {
31
+ const connected = session.connected_count ?? session.connected_accounts?.length ?? 0;
25
32
  return [
26
- `Posterly connect session: ${session.id}`,
33
+ `Posterly connect session created: ${session.id}`,
27
34
  `Platform: ${session.platform}`,
28
35
  `Status: ${session.status}`,
29
36
  `Message: ${session.status_message}`,
30
- `Connection URL: ${session.connect_url}`,
37
+ `Secure connection URL: ${session.connect_url}`,
31
38
  `Poll URL: ${session.poll_url}`,
32
- `Connected accounts: ${session.connected_count ?? session.connected_accounts?.length ?? 0}`,
33
- `Expires: ${session.expires_at}`,
39
+ `Connected accounts: ${connected}`,
40
+ `Accounts: ${formatConnectedAccounts(session.connected_accounts)}`,
41
+ `Expires: ${formatLocalDateTime(session.expires_at)}`,
42
+ `Dashboard connect page: ${DASHBOARD_CONNECT_URL}`,
34
43
  '',
35
- 'Next step: Open the connection URL for the user, then call get_connect_session with this session ID until the status is terminal.',
44
+ 'Next step for the AI agent: send the secure connection URL to the user, explain that Posterly will handle the browser OAuth step, then poll get_connect_session until the account is connected or the session ends.',
36
45
  includeRaw ? `\nRaw connect session:\n${JSON.stringify(session, null, 2)}` : '',
37
46
  ].filter(Boolean).join('\n');
38
47
  }
@@ -36,8 +36,10 @@ export declare const instagramSettingsSchema: z.ZodObject<{
36
36
  reel_cover_url: z.ZodOptional<z.ZodString>;
37
37
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
38
38
  }, "strip", z.ZodTypeAny, {
39
- __type?: "instagram" | "instagram-standalone" | undefined;
40
39
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
40
+ reel_cover_url?: string | undefined;
41
+ reel_thumb_offset?: number | undefined;
42
+ __type?: "instagram" | "instagram-standalone" | undefined;
41
43
  is_trial_reel?: boolean | undefined;
42
44
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
43
45
  collaborators?: (string | {
@@ -52,11 +54,11 @@ export declare const instagramSettingsSchema: z.ZodObject<{
52
54
  })[] | undefined;
53
55
  first_comment?: string | undefined;
54
56
  media_alt_texts?: Record<string, string> | undefined;
57
+ }, {
58
+ post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
55
59
  reel_cover_url?: string | undefined;
56
60
  reel_thumb_offset?: number | undefined;
57
- }, {
58
61
  __type?: "instagram" | "instagram-standalone" | undefined;
59
- post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
60
62
  is_trial_reel?: boolean | undefined;
61
63
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
62
64
  collaborators?: (string | {
@@ -71,8 +73,6 @@ export declare const instagramSettingsSchema: z.ZodObject<{
71
73
  })[] | undefined;
72
74
  first_comment?: string | undefined;
73
75
  media_alt_texts?: Record<string, string> | undefined;
74
- reel_cover_url?: string | undefined;
75
- reel_thumb_offset?: number | undefined;
76
76
  }>;
77
77
  export declare const platformSettingsSchema: z.ZodObject<{
78
78
  __type: z.ZodOptional<z.ZodString>;
@@ -265,8 +265,10 @@ export declare const createPostInputSchema: z.ZodObject<{
265
265
  reel_cover_url: z.ZodOptional<z.ZodString>;
266
266
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
267
267
  }, "strip", z.ZodTypeAny, {
268
- __type?: "instagram" | "instagram-standalone" | undefined;
269
268
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
269
+ reel_cover_url?: string | undefined;
270
+ reel_thumb_offset?: number | undefined;
271
+ __type?: "instagram" | "instagram-standalone" | undefined;
270
272
  is_trial_reel?: boolean | undefined;
271
273
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
272
274
  collaborators?: (string | {
@@ -281,11 +283,11 @@ export declare const createPostInputSchema: z.ZodObject<{
281
283
  })[] | undefined;
282
284
  first_comment?: string | undefined;
283
285
  media_alt_texts?: Record<string, string> | undefined;
286
+ }, {
287
+ post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
284
288
  reel_cover_url?: string | undefined;
285
289
  reel_thumb_offset?: number | undefined;
286
- }, {
287
290
  __type?: "instagram" | "instagram-standalone" | undefined;
288
- post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
289
291
  is_trial_reel?: boolean | undefined;
290
292
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
291
293
  collaborators?: (string | {
@@ -300,8 +302,6 @@ export declare const createPostInputSchema: z.ZodObject<{
300
302
  })[] | undefined;
301
303
  first_comment?: string | undefined;
302
304
  media_alt_texts?: Record<string, string> | undefined;
303
- reel_cover_url?: string | undefined;
304
- reel_thumb_offset?: number | undefined;
305
305
  }>>;
306
306
  platform_settings: z.ZodOptional<z.ZodObject<{
307
307
  __type: z.ZodOptional<z.ZodString>;
@@ -453,16 +453,18 @@ export declare const createPostInputSchema: z.ZodObject<{
453
453
  workspace_id?: string | undefined;
454
454
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
455
455
  account_id?: string | undefined;
456
- post_type?: string | undefined;
457
- username?: string | undefined;
458
- caption?: string | undefined;
459
456
  scheduled_at?: string | undefined;
460
457
  media_url?: string | undefined;
461
458
  media_urls?: string[] | undefined;
459
+ post_type?: string | undefined;
460
+ username?: string | undefined;
461
+ caption?: string | undefined;
462
462
  thread_posts?: string[] | undefined;
463
463
  instagram_settings?: {
464
- __type?: "instagram" | "instagram-standalone" | undefined;
465
464
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
465
+ reel_cover_url?: string | undefined;
466
+ reel_thumb_offset?: number | undefined;
467
+ __type?: "instagram" | "instagram-standalone" | undefined;
466
468
  is_trial_reel?: boolean | undefined;
467
469
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
468
470
  collaborators?: (string | {
@@ -477,8 +479,6 @@ export declare const createPostInputSchema: z.ZodObject<{
477
479
  })[] | undefined;
478
480
  first_comment?: string | undefined;
479
481
  media_alt_texts?: Record<string, string> | undefined;
480
- reel_cover_url?: string | undefined;
481
- reel_thumb_offset?: number | undefined;
482
482
  } | undefined;
483
483
  platform_settings?: z.objectOutputType<{
484
484
  __type: z.ZodOptional<z.ZodString>;
@@ -533,16 +533,18 @@ export declare const createPostInputSchema: z.ZodObject<{
533
533
  workspace_id?: string | undefined;
534
534
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
535
535
  account_id?: string | undefined;
536
- post_type?: string | undefined;
537
- username?: string | undefined;
538
- caption?: string | undefined;
539
536
  scheduled_at?: string | undefined;
540
537
  media_url?: string | undefined;
541
538
  media_urls?: string[] | undefined;
539
+ post_type?: string | undefined;
540
+ username?: string | undefined;
541
+ caption?: string | undefined;
542
542
  thread_posts?: string[] | undefined;
543
543
  instagram_settings?: {
544
- __type?: "instagram" | "instagram-standalone" | undefined;
545
544
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
545
+ reel_cover_url?: string | undefined;
546
+ reel_thumb_offset?: number | undefined;
547
+ __type?: "instagram" | "instagram-standalone" | undefined;
546
548
  is_trial_reel?: boolean | undefined;
547
549
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
548
550
  collaborators?: (string | {
@@ -557,8 +559,6 @@ export declare const createPostInputSchema: z.ZodObject<{
557
559
  })[] | undefined;
558
560
  first_comment?: string | undefined;
559
561
  media_alt_texts?: Record<string, string> | undefined;
560
- reel_cover_url?: string | undefined;
561
- reel_thumb_offset?: number | undefined;
562
562
  } | undefined;
563
563
  platform_settings?: z.objectInputType<{
564
564
  __type: z.ZodOptional<z.ZodString>;
@@ -661,8 +661,10 @@ export declare const createPostTool: {
661
661
  reel_cover_url: z.ZodOptional<z.ZodString>;
662
662
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
663
663
  }, "strip", z.ZodTypeAny, {
664
- __type?: "instagram" | "instagram-standalone" | undefined;
665
664
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
665
+ reel_cover_url?: string | undefined;
666
+ reel_thumb_offset?: number | undefined;
667
+ __type?: "instagram" | "instagram-standalone" | undefined;
666
668
  is_trial_reel?: boolean | undefined;
667
669
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
668
670
  collaborators?: (string | {
@@ -677,11 +679,11 @@ export declare const createPostTool: {
677
679
  })[] | undefined;
678
680
  first_comment?: string | undefined;
679
681
  media_alt_texts?: Record<string, string> | undefined;
682
+ }, {
683
+ post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
680
684
  reel_cover_url?: string | undefined;
681
685
  reel_thumb_offset?: number | undefined;
682
- }, {
683
686
  __type?: "instagram" | "instagram-standalone" | undefined;
684
- post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
685
687
  is_trial_reel?: boolean | undefined;
686
688
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
687
689
  collaborators?: (string | {
@@ -696,8 +698,6 @@ export declare const createPostTool: {
696
698
  })[] | undefined;
697
699
  first_comment?: string | undefined;
698
700
  media_alt_texts?: Record<string, string> | undefined;
699
- reel_cover_url?: string | undefined;
700
- reel_thumb_offset?: number | undefined;
701
701
  }>>;
702
702
  platform_settings: z.ZodOptional<z.ZodObject<{
703
703
  __type: z.ZodOptional<z.ZodString>;
@@ -849,16 +849,18 @@ export declare const createPostTool: {
849
849
  workspace_id?: string | undefined;
850
850
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
851
851
  account_id?: string | undefined;
852
- post_type?: string | undefined;
853
- username?: string | undefined;
854
- caption?: string | undefined;
855
852
  scheduled_at?: string | undefined;
856
853
  media_url?: string | undefined;
857
854
  media_urls?: string[] | undefined;
855
+ post_type?: string | undefined;
856
+ username?: string | undefined;
857
+ caption?: string | undefined;
858
858
  thread_posts?: string[] | undefined;
859
859
  instagram_settings?: {
860
- __type?: "instagram" | "instagram-standalone" | undefined;
861
860
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
861
+ reel_cover_url?: string | undefined;
862
+ reel_thumb_offset?: number | undefined;
863
+ __type?: "instagram" | "instagram-standalone" | undefined;
862
864
  is_trial_reel?: boolean | undefined;
863
865
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
864
866
  collaborators?: (string | {
@@ -873,8 +875,6 @@ export declare const createPostTool: {
873
875
  })[] | undefined;
874
876
  first_comment?: string | undefined;
875
877
  media_alt_texts?: Record<string, string> | undefined;
876
- reel_cover_url?: string | undefined;
877
- reel_thumb_offset?: number | undefined;
878
878
  } | undefined;
879
879
  platform_settings?: z.objectOutputType<{
880
880
  __type: z.ZodOptional<z.ZodString>;
@@ -929,16 +929,18 @@ export declare const createPostTool: {
929
929
  workspace_id?: string | undefined;
930
930
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
931
931
  account_id?: string | undefined;
932
- post_type?: string | undefined;
933
- username?: string | undefined;
934
- caption?: string | undefined;
935
932
  scheduled_at?: string | undefined;
936
933
  media_url?: string | undefined;
937
934
  media_urls?: string[] | undefined;
935
+ post_type?: string | undefined;
936
+ username?: string | undefined;
937
+ caption?: string | undefined;
938
938
  thread_posts?: string[] | undefined;
939
939
  instagram_settings?: {
940
- __type?: "instagram" | "instagram-standalone" | undefined;
941
940
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
941
+ reel_cover_url?: string | undefined;
942
+ reel_thumb_offset?: number | undefined;
943
+ __type?: "instagram" | "instagram-standalone" | undefined;
942
944
  is_trial_reel?: boolean | undefined;
943
945
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
944
946
  collaborators?: (string | {
@@ -953,8 +955,6 @@ export declare const createPostTool: {
953
955
  })[] | undefined;
954
956
  first_comment?: string | undefined;
955
957
  media_alt_texts?: Record<string, string> | undefined;
956
- reel_cover_url?: string | undefined;
957
- reel_thumb_offset?: number | undefined;
958
958
  } | undefined;
959
959
  platform_settings?: z.objectInputType<{
960
960
  __type: z.ZodOptional<z.ZodString>;
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { dashboardUrlForPost, formatLocalDateTime } from '../lib/format.js';
2
3
  import { SUPPORTED_PLATFORM_INPUTS, SUPPORTED_PLATFORM_IDS } from '../generated/platform-manifest.js';
3
4
  export const instagramSettingsSchema = z.object({
4
5
  __type: z.enum(['instagram', 'instagram-standalone']).optional(),
@@ -149,6 +150,7 @@ export const createPostTool = {
149
150
  '2. Show the user a preview containing ALL of: account(s) and platform(s), final caption text, scheduled time (in the user\'s timezone), media attached (if any), and workspace name.\n' +
150
151
  '3. Get explicit confirmation from the user (e.g. "post it", "yes schedule that", "looks good") BEFORE calling this tool. Do NOT infer consent from earlier instructions like "post about X every Monday" — confirm each individual post or the entire batch.\n' +
151
152
  '4. If scheduling multiple posts in one turn, list every post first and confirm the batch as a whole, then prefer `create_posts_batch` so they are created in one API request.\n\n' +
153
+ 'AFTER CALLING: Tell the user the post was created, include the Posterly dashboard link returned by the tool, and offer the next natural action. Do not narrate raw HTTP, curl, or API plumbing.\n\n' +
152
154
  'Provide either account_id OR username+platform to identify the account. If scheduled_at is omitted, the post publishes immediately. If workspace_id is omitted, the server resolves one from the social account, falling back to the caller\'s default (personal) workspace — pass workspace_id explicitly if the user has more than one workspace.\n\n' +
153
155
  'THREADS: Pass `thread_posts` (an array of 2+ strings) to schedule a multi-post thread on X (Twitter) or Threads (Meta). The first entry is the lead post; the rest are published as replies in the same chain. X entries are capped at 280 characters each (4000 for verified, 25000 for organization accounts); Threads entries are capped at 500 characters each. When `thread_posts` is set, `caption` is ignored.\n\n' +
154
156
  'PLATFORM SETTINGS: Pass `platform_settings` for composer-equivalent controls: Facebook story/reel/backgrounds, YouTube title/privacy/thumbnail/playlist, LinkedIn document titles/mentions/video thumbnails, TikTok direct-post privacy/toggles/commercial disclosure, Pinterest post_type (image/video/carousel), board (from pinterest.boards helper), title, link, and cover_image_url (video Pins), GBP event/offer/CTA, X reply settings/polls, Threads reply controls/text attachments, Bluesky languages/alt text, and Instagram feed/story/reel/carousel/collaborators/first comments/trial Reels. `instagram_settings` remains as a backwards-compatible alias.',
@@ -159,16 +161,17 @@ export const createPostTool = {
159
161
  const result = await client.createPost(payload);
160
162
  const p = result.post;
161
163
  const ws = result.workspace;
162
- const when = p.scheduled_at
163
- ? new Date(p.scheduled_at).toLocaleString()
164
- : 'now';
164
+ const when = p.scheduled_at ? formatLocalDateTime(p.scheduled_at) : 'now';
165
+ const dashboardUrl = dashboardUrlForPost({ id: p.id, scheduled_at: p.scheduled_at });
166
+ const createdLine = p.scheduled_at ? 'Post scheduled successfully.' : 'Post created successfully.';
165
167
  const lines = [
166
- 'Post created successfully!',
168
+ createdLine,
167
169
  `• ID: ${p.id}`,
168
170
  `• Platform: ${p.platform || input.platform || 'unknown'}`,
169
171
  `• Type: ${p.post_type}`,
170
172
  `• Status: ${p.status}`,
171
173
  `• Scheduled: ${when}`,
174
+ `• View in Posterly: ${dashboardUrl}`,
172
175
  ];
173
176
  if (thread_posts) {
174
177
  lines.push(`• Thread: ${thread_posts.length} posts`);
@@ -185,6 +188,7 @@ export const createPostTool = {
185
188
  if (ws) {
186
189
  lines.push(`• Workspace: ${ws.name} (${ws.id}) — resolved from ${ws.resolved_from}`);
187
190
  }
191
+ lines.push('', 'Next step for the AI agent: tell the user the post is in Posterly, share the dashboard link above, then ask whether they want to create another post, adjust this one, or connect another account.');
188
192
  return lines.join('\n');
189
193
  },
190
194
  };
@@ -51,8 +51,10 @@ export declare const createPostsBatchTool: {
51
51
  reel_cover_url: z.ZodOptional<z.ZodString>;
52
52
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
53
53
  }, "strip", z.ZodTypeAny, {
54
- __type?: "instagram" | "instagram-standalone" | undefined;
55
54
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
55
+ reel_cover_url?: string | undefined;
56
+ reel_thumb_offset?: number | undefined;
57
+ __type?: "instagram" | "instagram-standalone" | undefined;
56
58
  is_trial_reel?: boolean | undefined;
57
59
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
58
60
  collaborators?: (string | {
@@ -67,11 +69,11 @@ export declare const createPostsBatchTool: {
67
69
  })[] | undefined;
68
70
  first_comment?: string | undefined;
69
71
  media_alt_texts?: Record<string, string> | undefined;
72
+ }, {
73
+ post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
70
74
  reel_cover_url?: string | undefined;
71
75
  reel_thumb_offset?: number | undefined;
72
- }, {
73
76
  __type?: "instagram" | "instagram-standalone" | undefined;
74
- post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
75
77
  is_trial_reel?: boolean | undefined;
76
78
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
77
79
  collaborators?: (string | {
@@ -86,8 +88,6 @@ export declare const createPostsBatchTool: {
86
88
  })[] | undefined;
87
89
  first_comment?: string | undefined;
88
90
  media_alt_texts?: Record<string, string> | undefined;
89
- reel_cover_url?: string | undefined;
90
- reel_thumb_offset?: number | undefined;
91
91
  }>>;
92
92
  platform_settings: z.ZodOptional<z.ZodObject<{
93
93
  __type: z.ZodOptional<z.ZodString>;
@@ -239,16 +239,18 @@ export declare const createPostsBatchTool: {
239
239
  workspace_id?: string | undefined;
240
240
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
241
241
  account_id?: string | undefined;
242
- post_type?: string | undefined;
243
- username?: string | undefined;
244
- caption?: string | undefined;
245
242
  scheduled_at?: string | undefined;
246
243
  media_url?: string | undefined;
247
244
  media_urls?: string[] | undefined;
245
+ post_type?: string | undefined;
246
+ username?: string | undefined;
247
+ caption?: string | undefined;
248
248
  thread_posts?: string[] | undefined;
249
249
  instagram_settings?: {
250
- __type?: "instagram" | "instagram-standalone" | undefined;
251
250
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
251
+ reel_cover_url?: string | undefined;
252
+ reel_thumb_offset?: number | undefined;
253
+ __type?: "instagram" | "instagram-standalone" | undefined;
252
254
  is_trial_reel?: boolean | undefined;
253
255
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
254
256
  collaborators?: (string | {
@@ -263,8 +265,6 @@ export declare const createPostsBatchTool: {
263
265
  })[] | undefined;
264
266
  first_comment?: string | undefined;
265
267
  media_alt_texts?: Record<string, string> | undefined;
266
- reel_cover_url?: string | undefined;
267
- reel_thumb_offset?: number | undefined;
268
268
  } | undefined;
269
269
  platform_settings?: z.objectOutputType<{
270
270
  __type: z.ZodOptional<z.ZodString>;
@@ -319,16 +319,18 @@ export declare const createPostsBatchTool: {
319
319
  workspace_id?: string | undefined;
320
320
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
321
321
  account_id?: string | undefined;
322
- post_type?: string | undefined;
323
- username?: string | undefined;
324
- caption?: string | undefined;
325
322
  scheduled_at?: string | undefined;
326
323
  media_url?: string | undefined;
327
324
  media_urls?: string[] | undefined;
325
+ post_type?: string | undefined;
326
+ username?: string | undefined;
327
+ caption?: string | undefined;
328
328
  thread_posts?: string[] | undefined;
329
329
  instagram_settings?: {
330
- __type?: "instagram" | "instagram-standalone" | undefined;
331
330
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
331
+ reel_cover_url?: string | undefined;
332
+ reel_thumb_offset?: number | undefined;
333
+ __type?: "instagram" | "instagram-standalone" | undefined;
332
334
  is_trial_reel?: boolean | undefined;
333
335
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
334
336
  collaborators?: (string | {
@@ -343,8 +345,6 @@ export declare const createPostsBatchTool: {
343
345
  })[] | undefined;
344
346
  first_comment?: string | undefined;
345
347
  media_alt_texts?: Record<string, string> | undefined;
346
- reel_cover_url?: string | undefined;
347
- reel_thumb_offset?: number | undefined;
348
348
  } | undefined;
349
349
  platform_settings?: z.objectInputType<{
350
350
  __type: z.ZodOptional<z.ZodString>;
@@ -401,16 +401,18 @@ export declare const createPostsBatchTool: {
401
401
  workspace_id?: string | undefined;
402
402
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
403
403
  account_id?: string | undefined;
404
- post_type?: string | undefined;
405
- username?: string | undefined;
406
- caption?: string | undefined;
407
404
  scheduled_at?: string | undefined;
408
405
  media_url?: string | undefined;
409
406
  media_urls?: string[] | undefined;
407
+ post_type?: string | undefined;
408
+ username?: string | undefined;
409
+ caption?: string | undefined;
410
410
  thread_posts?: string[] | undefined;
411
411
  instagram_settings?: {
412
- __type?: "instagram" | "instagram-standalone" | undefined;
413
412
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
413
+ reel_cover_url?: string | undefined;
414
+ reel_thumb_offset?: number | undefined;
415
+ __type?: "instagram" | "instagram-standalone" | undefined;
414
416
  is_trial_reel?: boolean | undefined;
415
417
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
416
418
  collaborators?: (string | {
@@ -425,8 +427,6 @@ export declare const createPostsBatchTool: {
425
427
  })[] | undefined;
426
428
  first_comment?: string | undefined;
427
429
  media_alt_texts?: Record<string, string> | undefined;
428
- reel_cover_url?: string | undefined;
429
- reel_thumb_offset?: number | undefined;
430
430
  } | undefined;
431
431
  platform_settings?: z.objectOutputType<{
432
432
  __type: z.ZodOptional<z.ZodString>;
@@ -483,16 +483,18 @@ export declare const createPostsBatchTool: {
483
483
  workspace_id?: string | undefined;
484
484
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
485
485
  account_id?: string | undefined;
486
- post_type?: string | undefined;
487
- username?: string | undefined;
488
- caption?: string | undefined;
489
486
  scheduled_at?: string | undefined;
490
487
  media_url?: string | undefined;
491
488
  media_urls?: string[] | undefined;
489
+ post_type?: string | undefined;
490
+ username?: string | undefined;
491
+ caption?: string | undefined;
492
492
  thread_posts?: string[] | undefined;
493
493
  instagram_settings?: {
494
- __type?: "instagram" | "instagram-standalone" | undefined;
495
494
  post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
495
+ reel_cover_url?: string | undefined;
496
+ reel_thumb_offset?: number | undefined;
497
+ __type?: "instagram" | "instagram-standalone" | undefined;
496
498
  is_trial_reel?: boolean | undefined;
497
499
  graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
498
500
  collaborators?: (string | {
@@ -507,8 +509,6 @@ export declare const createPostsBatchTool: {
507
509
  })[] | undefined;
508
510
  first_comment?: string | undefined;
509
511
  media_alt_texts?: Record<string, string> | undefined;
510
- reel_cover_url?: string | undefined;
511
- reel_thumb_offset?: number | undefined;
512
512
  } | undefined;
513
513
  platform_settings?: z.objectInputType<{
514
514
  __type: z.ZodOptional<z.ZodString>;
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { dashboardUrlForPostList, formatLocalDateTime } from '../lib/format.js';
2
3
  import { buildCreatePostPayload, createPostInputSchema } from './create-post.js';
3
4
  export const createPostsBatchTool = {
4
5
  name: 'create_posts_batch',
@@ -7,6 +8,7 @@ export const createPostsBatchTool = {
7
8
  '1. Call `whoami` at the start of any new session to confirm which workspace and user you are acting for.\n' +
8
9
  '2. Show the user a preview of EVERY post: account/platform, final caption or thread text, scheduled time in their timezone, media, platform settings, and workspace.\n' +
9
10
  '3. Get explicit confirmation for the whole batch before calling. Do not infer consent from an earlier content plan.\n\n' +
11
+ 'AFTER CALLING: Summarize the batch result in natural language, include the Posterly dashboard link returned by the tool, and avoid narrating raw HTTP, curl, or API plumbing.\n\n' +
10
12
  'Each item accepts the same fields as `create_post`, including `thread_posts`, `platform_settings`, `instagram_settings`, media URLs, and workspace_id. The endpoint may partially succeed; failed items are returned with their index.',
11
13
  inputSchema: z.object({
12
14
  posts: z
@@ -18,21 +20,25 @@ export const createPostsBatchTool = {
18
20
  async execute(client, input) {
19
21
  const payloads = input.posts.map((post) => buildCreatePostPayload(post));
20
22
  const result = await client.createPostsBatch({ posts: payloads });
23
+ const createdPosts = result.posts.map((item) => item.post);
24
+ const dashboardUrl = dashboardUrlForPostList(createdPosts);
21
25
  const lines = [
22
26
  'Batch create completed.',
23
27
  `• Total: ${result.total}`,
24
28
  `• Created: ${result.created}`,
25
29
  `• Replayed: ${result.replayed}`,
26
30
  `• Failed: ${result.failed}`,
31
+ `• View in Posterly: ${dashboardUrl}`,
27
32
  ];
28
33
  for (const item of result.posts.slice(0, 25)) {
29
34
  const post = item.post;
30
- const when = post.scheduled_at ? new Date(post.scheduled_at).toLocaleString() : 'now';
35
+ const when = post.scheduled_at ? formatLocalDateTime(post.scheduled_at) : 'now';
31
36
  lines.push(`• [${item.index}] ID ${post.id} ${post.platform || 'unknown'} ${post.post_type || 'post'} ${post.status || 'created'} at ${when}${item.replayed ? ' (replayed)' : ''}`);
32
37
  }
33
38
  for (const error of result.errors.slice(0, 25)) {
34
39
  lines.push(`• [${error.index}] ERROR ${error.status}: ${error.error}`);
35
40
  }
41
+ lines.push('', 'Next step for the AI agent: tell the user which posts were created, share the dashboard link above, and ask whether they want to review the queue, adjust anything, or create the next post.');
36
42
  return lines.join('\n');
37
43
  },
38
44
  };