posterly-mcp-server 0.45.0 → 0.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/version.d.ts +1 -1
  3. package/dist/lib/version.js +1 -1
  4. package/dist/tools/create-post.d.ts +24 -1
  5. package/dist/tools/create-post.js +72 -6
  6. package/dist/tools/create-posts-batch.js +14 -2
  7. package/dist/tools/validate-post.js +2 -2
  8. package/package.json +1 -1
  9. package/scripts/test-payload-builders.mjs +143 -20
  10. package/server.json +2 -2
  11. package/src/lib/version.ts +1 -1
  12. package/src/tools/create-post.ts +84 -9
  13. package/src/tools/create-posts-batch.ts +13 -2
  14. package/src/tools/validate-post.ts +2 -1
  15. package/dist/tools/add-google-business-media.d.ts +0 -42
  16. package/dist/tools/add-google-business-media.js +0 -34
  17. package/dist/tools/create-oauth-client.d.ts +0 -40
  18. package/dist/tools/create-oauth-client.js +0 -20
  19. package/dist/tools/delete-comment.d.ts +0 -24
  20. package/dist/tools/delete-comment.js +0 -22
  21. package/dist/tools/delete-google-business-media.d.ts +0 -32
  22. package/dist/tools/delete-google-business-media.js +0 -17
  23. package/dist/tools/delete-google-business-review-reply.d.ts +0 -32
  24. package/dist/tools/delete-google-business-review-reply.js +0 -17
  25. package/dist/tools/delete-oauth-client.d.ts +0 -20
  26. package/dist/tools/delete-oauth-client.js +0 -13
  27. package/dist/tools/delete-post-group.d.ts +0 -20
  28. package/dist/tools/delete-post-group.js +0 -13
  29. package/dist/tools/delete-webhook.d.ts +0 -20
  30. package/dist/tools/delete-webhook.js +0 -13
  31. package/dist/tools/get-account-analytics.d.ts +0 -31
  32. package/dist/tools/get-account-analytics.js +0 -152
  33. package/dist/tools/get-brand-profile.d.ts +0 -16
  34. package/dist/tools/get-brand-profile.js +0 -73
  35. package/dist/tools/get-brand.d.ts +0 -16
  36. package/dist/tools/get-brand.js +0 -26
  37. package/dist/tools/get-comment.d.ts +0 -20
  38. package/dist/tools/get-comment.js +0 -36
  39. package/dist/tools/get-connect-link.d.ts +0 -28
  40. package/dist/tools/get-connect-link.js +0 -51
  41. package/dist/tools/get-connect-session.d.ts +0 -20
  42. package/dist/tools/get-connect-session.js +0 -54
  43. package/dist/tools/get-conversation.d.ts +0 -24
  44. package/dist/tools/get-conversation.js +0 -31
  45. package/dist/tools/get-google-business-review-link.d.ts +0 -24
  46. package/dist/tools/get-google-business-review-link.js +0 -19
  47. package/dist/tools/get-image-job.d.ts +0 -24
  48. package/dist/tools/get-image-job.js +0 -31
  49. package/dist/tools/get-learned-voice.d.ts +0 -16
  50. package/dist/tools/get-learned-voice.js +0 -22
  51. package/dist/tools/get-mcp-status.d.ts +0 -8
  52. package/dist/tools/get-mcp-status.js +0 -182
  53. package/dist/tools/get-performance-profile.d.ts +0 -16
  54. package/dist/tools/get-performance-profile.js +0 -39
  55. package/dist/tools/get-platform-schema.d.ts +0 -24
  56. package/dist/tools/get-platform-schema.js +0 -48
  57. package/dist/tools/get-post-analytics.d.ts +0 -39
  58. package/dist/tools/get-post-analytics.js +0 -222
  59. package/dist/tools/get-post-insights.d.ts +0 -28
  60. package/dist/tools/get-post-insights.js +0 -39
  61. package/dist/tools/get-post-missing.d.ts +0 -16
  62. package/dist/tools/get-post-missing.js +0 -12
  63. package/dist/tools/get-video-job.d.ts +0 -24
  64. package/dist/tools/get-video-job.js +0 -31
  65. package/dist/tools/list-brand-accounts.d.ts +0 -16
  66. package/dist/tools/list-brand-accounts.js +0 -24
  67. package/dist/tools/reply-google-business-review.d.ts +0 -36
  68. package/dist/tools/reply-google-business-review.js +0 -18
  69. package/dist/tools/reply-to-comment.d.ts +0 -32
  70. package/dist/tools/reply-to-comment.js +0 -17
  71. package/dist/tools/send-message.d.ts +0 -28
  72. package/dist/tools/send-message.js +0 -16
  73. package/dist/tools/suggest-google-business-review-reply.d.ts +0 -48
  74. package/dist/tools/suggest-google-business-review-reply.js +0 -27
  75. package/dist/tools/sync-inbox.d.ts +0 -24
  76. package/dist/tools/sync-inbox.js +0 -18
  77. package/dist/tools/test-webhook.d.ts +0 -20
  78. package/dist/tools/test-webhook.js +0 -14
  79. package/dist/tools/update-comment.d.ts +0 -28
  80. package/dist/tools/update-comment.js +0 -21
  81. package/dist/tools/update-oauth-client.d.ts +0 -44
  82. package/dist/tools/update-oauth-client.js +0 -21
  83. package/dist/tools/update-post-release-id.d.ts +0 -28
  84. package/dist/tools/update-post-release-id.js +0 -18
  85. package/dist/tools/update-post-status.d.ts +0 -28
  86. package/dist/tools/update-post-status.js +0 -23
  87. package/dist/tools/update-webhook.d.ts +0 -40
  88. package/dist/tools/update-webhook.js +0 -21
  89. package/dist/tools/upload-media-from-url.d.ts +0 -24
  90. package/dist/tools/upload-media-from-url.js +0 -26
@@ -1,73 +0,0 @@
1
- import { z } from 'zod';
2
- import { code, compactText, formatDateTime, mdLearnedVoice, mdKeyValue, mdSection, mdTitle } from '../lib/format.js';
3
- export const getBrandProfileTool = {
4
- name: 'get_brand_profile',
5
- description: 'Get the extended brand profile for a brand/client. Returns voice/tone guidance, audience, keywords, dos and don’ts, visual notes, and other saved brand context.',
6
- inputSchema: z.object({
7
- brand_id: z.string().describe('The brand ID to inspect (from list_brands).'),
8
- }),
9
- async execute(client, input) {
10
- const result = await client.getBrandProfile(input.brand_id);
11
- const profile = result.brand_profile;
12
- const profileBody = [
13
- mdKeyValue([
14
- ['Source', profile.source],
15
- ['Profile ID', profile.id ? code(profile.id) : undefined],
16
- ['Workspace client ID', profile.workspace_client_id ? code(profile.workspace_client_id) : undefined],
17
- ['Legacy brand group ID', profile.brand_group_id ? code(profile.brand_group_id) : undefined],
18
- ['Logo', profile.logo_url],
19
- ['Last refreshed', profile.last_context_refresh_at ? formatDateTime(profile.last_context_refresh_at) : undefined],
20
- ]),
21
- mdSection('Voice and audience', mdKeyValue([
22
- ['Tone of voice', compactText(profile.tone_of_voice, 180)],
23
- ['Audience', compactText(profile.audience, 180)],
24
- ['Brand values', compactText(profile.brand_values, 180)],
25
- ['Brand story', compactText(formatStructuredValue(profile.brand_story), 240)],
26
- ])),
27
- mdSection('Guidance', mdKeyValue([
28
- ['Custom instructions', compactText(profile.custom_instructions, 240)],
29
- ['Keywords', formatStructuredValue(profile.keywords)],
30
- ['Competitors', formatStructuredValue(profile.competitors)],
31
- ['Do / Don’ts', formatStructuredValue(profile.do_donts)],
32
- ['Topics to cover', formatStructuredValue(profile.topics_to_cover)],
33
- ['Topics to avoid', formatStructuredValue(profile.topics_to_avoid)],
34
- ])),
35
- mdSection('Creative references', mdKeyValue([
36
- ['Visual guidelines', formatStructuredValue(profile.visual_guidelines)],
37
- ['Example posts', formatStructuredValue(profile.example_posts)],
38
- ['Voice examples', formatStructuredValue(profile.voice_examples)],
39
- ])),
40
- ].filter(Boolean).join('\n\n');
41
- const learnedVoices = (Array.isArray(profile.learned_voice) ? profile.learned_voice : []);
42
- const learnedBody = learnedVoices.length
43
- ? mdSection('Learned voice (from published captions)', learnedVoices.map((voice) => mdLearnedVoice(voice)).filter(Boolean).join('\n\n'))
44
- : '';
45
- return [
46
- mdTitle(`Brand profile: ${profile.brand_name}`),
47
- profileBody || 'No extended brand profile fields have been saved yet.',
48
- learnedBody ||
49
- '_No learned voice yet. posterly learns each account’s voice automatically once it has enough published posts._',
50
- ].filter(Boolean).join('\n\n');
51
- },
52
- };
53
- function formatStructuredValue(value) {
54
- if (value == null)
55
- return null;
56
- if (typeof value === 'string') {
57
- const trimmed = value.trim();
58
- return trimmed.length > 0 ? trimmed : null;
59
- }
60
- if (Array.isArray(value)) {
61
- if (value.length === 0)
62
- return null;
63
- return value
64
- .map((item) => formatStructuredValue(item) || JSON.stringify(item))
65
- .filter(Boolean)
66
- .join(' | ');
67
- }
68
- if (typeof value === 'object') {
69
- const json = JSON.stringify(value);
70
- return json === '{}' ? null : json;
71
- }
72
- return String(value);
73
- }
@@ -1,16 +0,0 @@
1
- import { z } from 'zod';
2
- import type { PosterlyClient } from '../lib/api-client.js';
3
- export declare const getBrandTool: {
4
- name: string;
5
- description: string;
6
- inputSchema: z.ZodObject<{
7
- brand_id: z.ZodString;
8
- }, "strip", z.ZodTypeAny, {
9
- brand_id: string;
10
- }, {
11
- brand_id: string;
12
- }>;
13
- execute(client: PosterlyClient, input: {
14
- brand_id: string;
15
- }): Promise<string>;
16
- };
@@ -1,26 +0,0 @@
1
- import { z } from 'zod';
2
- import { code, formatDateTime, mdKeyValue, mdTitle } from '../lib/format.js';
3
- export const getBrandTool = {
4
- name: 'get_brand',
5
- description: 'Get one brand/client by ID. Returns its workspace, source, linked legacy brand group if present, and the number of social accounts assigned to it.',
6
- inputSchema: z.object({
7
- brand_id: z.string().describe('The brand ID to look up (from list_brands).'),
8
- }),
9
- async execute(client, input) {
10
- const result = await client.getBrand(input.brand_id);
11
- const brand = result.brand;
12
- return [
13
- mdTitle(`Brand: ${brand.name}`),
14
- mdKeyValue([
15
- ['Brand ID', code(brand.id)],
16
- ['Source', brand.source],
17
- ['Workspace', brand.workspace_id ? code(brand.workspace_id) : 'n/a'],
18
- ['Accounts assigned', brand.account_count ?? 0],
19
- ['Workspace client ID', brand.workspace_client_id ? code(brand.workspace_client_id) : undefined],
20
- ['Legacy brand group ID', brand.legacy_brand_group_id ? code(brand.legacy_brand_group_id) : undefined],
21
- ['Created', formatDateTime(brand.created_at)],
22
- ['Updated', formatDateTime(brand.updated_at)],
23
- ]),
24
- ].join('\n\n');
25
- },
26
- };
@@ -1,20 +0,0 @@
1
- import { z } from 'zod';
2
- import type { PosterlyClient } from '../lib/api-client.js';
3
- export declare const getCommentTool: {
4
- name: string;
5
- description: string;
6
- inputSchema: z.ZodObject<{
7
- comment_id: z.ZodString;
8
- workspace_id: z.ZodOptional<z.ZodString>;
9
- }, "strip", z.ZodTypeAny, {
10
- comment_id: string;
11
- workspace_id?: string | undefined;
12
- }, {
13
- comment_id: string;
14
- workspace_id?: string | undefined;
15
- }>;
16
- execute(client: PosterlyClient, input: {
17
- comment_id: string;
18
- workspace_id?: string;
19
- }): Promise<string>;
20
- };
@@ -1,36 +0,0 @@
1
- import { z } from 'zod';
2
- import { formatLocalDateTime } from '../lib/format.js';
3
- export const getCommentTool = {
4
- name: 'get_comment',
5
- description: 'Get one social inbox comment and its replies. Instagram, Facebook Page, Threads, and LinkedIn Page comments. Requires a Pro plan or higher plus posts:read.',
6
- inputSchema: z.object({
7
- comment_id: z.string().min(1).describe('Comment ID from list_comments.'),
8
- workspace_id: z.string().optional().describe('Optional. Omit to search every workspace you belong to; pass a workspace ID from whoami to limit to one.'),
9
- }),
10
- async execute(client, input) {
11
- const result = await client.getComment(input);
12
- const comment = result.comment;
13
- const author = typeof comment.author_username === 'string' ? `@${comment.author_username}` : 'unknown';
14
- const lines = [
15
- `Comment ${String(comment.id)}`,
16
- `• Platform: ${typeof comment.platform === 'string' ? comment.platform : 'unknown'}`,
17
- `• Author: ${author}`,
18
- `• Hidden: ${comment.is_hidden ? 'yes' : 'no'}`,
19
- `• Read: ${comment.is_read === false ? 'no' : 'yes'}`,
20
- `• Posted: ${formatLocalDateTime(typeof comment.posted_at === 'string' ? comment.posted_at : null)}`,
21
- `• Content: ${typeof comment.content === 'string' ? comment.content : '(empty)'}`,
22
- ];
23
- if (typeof comment.media_permalink === 'string')
24
- lines.push(`• Media: ${comment.media_permalink}`);
25
- const replies = Array.isArray(comment.replies) ? comment.replies : [];
26
- if (replies.length > 0) {
27
- lines.push('', `Replies (${replies.length}):`);
28
- for (const reply of replies) {
29
- const row = reply;
30
- const replyAuthor = typeof row.author_username === 'string' ? `@${row.author_username}` : 'unknown';
31
- lines.push(`- ${String(row.id)} ${replyAuthor}: ${typeof row.content === 'string' ? row.content : '(empty)'}`);
32
- }
33
- }
34
- return lines.join('\n');
35
- },
36
- };
@@ -1,28 +0,0 @@
1
- import { z } from 'zod';
2
- import type { PosterlyClient } from '../lib/api-client.js';
3
- export declare const getConnectLinkTool: {
4
- name: string;
5
- description: string;
6
- inputSchema: z.ZodObject<{
7
- platform: z.ZodOptional<z.ZodEnum<["bluesky", "devto", "discord", "facebook", "facebook_instagram", "facebook_pages", "gmb", "google-business", "google_business", "google_business_profile", "hashnode", "instagram", "instagram-standalone", "instagram_direct", "lemmy", "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
- workspace_id: z.ZodOptional<z.ZodString>;
9
- include_planned: z.ZodOptional<z.ZodBoolean>;
10
- debug: z.ZodOptional<z.ZodBoolean>;
11
- }, "strip", z.ZodTypeAny, {
12
- platform?: "meta" | "instagram_direct" | "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "threads" | "linkedin" | "youtube" | "pinterest" | "google_business" | "medium" | "x" | "telegram" | "bluesky" | "discord" | "slack" | "mastodon" | "devto" | "hashnode" | "wordpress" | "lemmy" | "reddit" | "skool" | "whop" | "gmb" | "google-business" | "google_business_profile" | "linkedin_page" | "facebook_instagram" | "facebook_pages" | "linkedin-company" | "linkedin-page" | "linkedin_company" | "linkedin_personal" | "meta_business" | "x_twitter" | undefined;
13
- workspace_id?: string | undefined;
14
- include_planned?: boolean | undefined;
15
- debug?: boolean | undefined;
16
- }, {
17
- platform?: "meta" | "instagram_direct" | "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "threads" | "linkedin" | "youtube" | "pinterest" | "google_business" | "medium" | "x" | "telegram" | "bluesky" | "discord" | "slack" | "mastodon" | "devto" | "hashnode" | "wordpress" | "lemmy" | "reddit" | "skool" | "whop" | "gmb" | "google-business" | "google_business_profile" | "linkedin_page" | "facebook_instagram" | "facebook_pages" | "linkedin-company" | "linkedin-page" | "linkedin_company" | "linkedin_personal" | "meta_business" | "x_twitter" | undefined;
18
- workspace_id?: string | undefined;
19
- include_planned?: boolean | undefined;
20
- debug?: boolean | undefined;
21
- }>;
22
- execute(client: PosterlyClient, input: {
23
- platform?: string;
24
- workspace_id?: string;
25
- include_planned?: boolean;
26
- debug?: boolean;
27
- }): Promise<string>;
28
- };
@@ -1,51 +0,0 @@
1
- import { z } from 'zod';
2
- import { CONNECT_INPUTS, PLANNED_PLATFORM_IDS } from '../generated/platform-manifest.js';
3
- export const getConnectLinkTool = {
4
- name: 'get_connect_link',
5
- description: 'List dashboard handoff links/readiness for connecting social accounts, or get one platform connection URL. Use connection_url in a logged-in browser. Direct OAuth URLs are intentionally not exposed because provider callbacks rely on browser state. Credential-based platforms (telegram, bluesky, discord, wordpress, devto, hashnode, lemmy) can instead be connected headlessly with connect_account; this tool shows their credential_fields.',
6
- inputSchema: z.object({
7
- platform: z
8
- .enum(CONNECT_INPUTS)
9
- .optional()
10
- .describe('Connection target such as instagram, meta, linkedin_page, twitter, x, google_business, telegram, reddit, or wordpress. Omit to list live connection targets.'),
11
- workspace_id: z
12
- .string()
13
- .optional()
14
- .describe('Filter connected account counts to a workspace.'),
15
- include_planned: z
16
- .boolean()
17
- .optional()
18
- .describe(`Include planned provider expansion targets from the Postiz parity audit: ${PLANNED_PLATFORM_IDS.join(', ')}.`),
19
- debug: z
20
- .boolean()
21
- .optional()
22
- .describe('When true, include the raw connect option JSON for debugging. Keep false for normal user-facing agent flows.'),
23
- }),
24
- async execute(client, input) {
25
- const { debug, ...params } = input;
26
- const result = await client.getConnectLink(params);
27
- if (result.connect) {
28
- return formatConnectOption(result.connect, Boolean(debug));
29
- }
30
- const options = result.connect_options || [];
31
- const lines = options.map((option) => formatConnectOption(option, false));
32
- return `posterly connection options (${options.length}):\n${lines.join('\n\n')}`;
33
- },
34
- };
35
- function formatConnectOption(option, includeRaw) {
36
- const missing = option.missing_env?.length
37
- ? `missing env: ${option.missing_env.map((group) => group.join(' or ')).join(', ')}`
38
- : 'configured';
39
- const accounts = option.connected_count ?? option.connected_accounts?.length ?? 0;
40
- const fields = option.credential_fields?.length
41
- ? `; credential fields: ${option.credential_fields.map((field) => field.key).join(', ')}`
42
- : '';
43
- const scopes = option.scopes?.length ? `; scopes: ${option.scopes.join(', ')}` : '';
44
- const raw = includeRaw ? `\n\nRaw connect option:\n${JSON.stringify(option, null, 2)}` : '';
45
- return [
46
- `${option.label} (${option.platform})`,
47
- `Status: ${option.status}; method: ${option.method}; ${missing}; connected accounts: ${accounts}`,
48
- `Connection URL: ${option.connection_url || 'not available'}${fields}${scopes}`,
49
- raw,
50
- ].join('\n');
51
- }
@@ -1,20 +0,0 @@
1
- import { z } from 'zod';
2
- import type { PosterlyClient } from '../lib/api-client.js';
3
- export declare const getConnectSessionTool: {
4
- name: string;
5
- description: string;
6
- inputSchema: z.ZodObject<{
7
- session_id: z.ZodString;
8
- debug: z.ZodOptional<z.ZodBoolean>;
9
- }, "strip", z.ZodTypeAny, {
10
- session_id: string;
11
- debug?: boolean | undefined;
12
- }, {
13
- session_id: string;
14
- debug?: boolean | undefined;
15
- }>;
16
- execute(client: PosterlyClient, input: {
17
- session_id: string;
18
- debug?: boolean;
19
- }): Promise<string>;
20
- };
@@ -1,54 +0,0 @@
1
- import { z } from 'zod';
2
- import { DASHBOARD_CONNECT_URL, formatConnectedAccounts, formatLocalDateTime } from '../lib/format.js';
3
- export const getConnectSessionTool = {
4
- name: 'get_connect_session',
5
- description: 'Poll a posterly connect session. Use the returned status and next-step guidance to keep the user updated in plain language. Stop when status is connected, failed, cancelled, or expired.',
6
- inputSchema: z.object({
7
- session_id: z.string().describe('Connect session ID returned by create_connect_session.'),
8
- debug: z
9
- .boolean()
10
- .optional()
11
- .describe('When true, include the raw connect session JSON for debugging. Keep false for normal user-facing agent flows.'),
12
- }),
13
- async execute(client, input) {
14
- const result = await client.getConnectSession(input.session_id);
15
- return formatConnectSession(result.connect_session, Boolean(input.debug));
16
- },
17
- };
18
- function formatConnectSession(session, includeRaw) {
19
- const connected = session.connected_count ?? session.connected_accounts?.length ?? 0;
20
- return [
21
- `posterly connect session: ${session.id}`,
22
- `Platform: ${session.platform}`,
23
- `Status: ${session.status}`,
24
- `Message: ${session.status_message}`,
25
- `Connected accounts: ${connected}`,
26
- `Accounts: ${formatConnectedAccounts(session.connected_accounts)}`,
27
- session.error_message ? `Error: ${session.error_message}` : '',
28
- `Expires: ${formatLocalDateTime(session.expires_at)}`,
29
- `Dashboard connect page: ${DASHBOARD_CONNECT_URL}`,
30
- '',
31
- guidanceForStatus(session),
32
- includeRaw ? `\nRaw connect session:\n${JSON.stringify(session, null, 2)}` : '',
33
- ].filter(Boolean).join('\n');
34
- }
35
- function guidanceForStatus(session) {
36
- switch (session.status) {
37
- case 'created':
38
- case 'opened':
39
- case 'awaiting_provider':
40
- return 'Next step for the AI agent: tell the user posterly is waiting for browser approval, then keep polling this session. Do not ask for social passwords or OAuth codes.';
41
- case 'awaiting_credentials':
42
- return 'Next step for the AI agent: tell the user posterly needs them to finish the browser credential step, then keep polling. Do not ask the user to paste credentials into chat.';
43
- case 'connected':
44
- return `Next step for the AI agent: tell the user ${formatConnectedAccounts(session.connected_accounts)} is connected, then ask what they want to schedule first or offer to create a test post.`;
45
- case 'failed':
46
- return 'Next step for the AI agent: tell the user the connection failed, share the error if present, and offer to create a fresh connect session.';
47
- case 'cancelled':
48
- return 'Next step for the AI agent: tell the user the connection was cancelled and offer to create a fresh connect session when they are ready.';
49
- case 'expired':
50
- return 'Next step for the AI agent: tell the user the connection link expired and create a fresh connect session if they still want to connect this account.';
51
- default:
52
- return 'Next step for the AI agent: explain the current connection status in plain language and keep polling unless the session is terminal.';
53
- }
54
- }
@@ -1,24 +0,0 @@
1
- import { z } from 'zod';
2
- import type { PosterlyClient } from '../lib/api-client.js';
3
- export declare const getConversationTool: {
4
- name: string;
5
- description: string;
6
- inputSchema: z.ZodObject<{
7
- conversation_id: z.ZodString;
8
- workspace_id: z.ZodOptional<z.ZodString>;
9
- limit: z.ZodOptional<z.ZodNumber>;
10
- }, "strip", z.ZodTypeAny, {
11
- conversation_id: string;
12
- workspace_id?: string | undefined;
13
- limit?: number | undefined;
14
- }, {
15
- conversation_id: string;
16
- workspace_id?: string | undefined;
17
- limit?: number | undefined;
18
- }>;
19
- execute(client: PosterlyClient, input: {
20
- conversation_id: string;
21
- workspace_id?: string;
22
- limit?: number;
23
- }): Promise<string>;
24
- };
@@ -1,31 +0,0 @@
1
- import { z } from 'zod';
2
- import { formatLocalDateTime, truncateText } from '../lib/format.js';
3
- export const getConversationTool = {
4
- name: 'get_conversation',
5
- description: 'Get one social inbox DM conversation and its messages. Instagram and Facebook Page DMs only. Requires a Pro plan or higher plus posts:read.',
6
- inputSchema: z.object({
7
- conversation_id: z.string().min(1).describe('Conversation ID from list_conversations.'),
8
- workspace_id: z.string().optional().describe('Optional. Omit to search every workspace you belong to; pass a workspace ID from whoami to limit to one.'),
9
- limit: z.number().int().min(1).max(100).optional().describe('Maximum messages to return. Default 50, max 100.'),
10
- }),
11
- async execute(client, input) {
12
- const result = await client.getConversation(input);
13
- const conversation = result.conversation;
14
- const username = typeof conversation.participant_username === 'string' ? `@${conversation.participant_username}` : 'unknown';
15
- const lines = [
16
- `Conversation ${String(conversation.id)}`,
17
- `• Platform: ${typeof conversation.platform === 'string' ? conversation.platform : 'unknown'}`,
18
- `• Participant: ${username}`,
19
- `• Read: ${conversation.is_read === false ? 'no' : 'yes'}`,
20
- `• Messages: ${result.messages.length}`,
21
- '',
22
- ];
23
- for (const message of result.messages) {
24
- const who = message.sender_is_business ? 'you' : (typeof message.sender_username === 'string' ? message.sender_username : 'them');
25
- const when = formatLocalDateTime(typeof message.sent_at === 'string' ? message.sent_at : null);
26
- const text = truncateText(typeof message.content === 'string' ? message.content : '', 240);
27
- lines.push(`- [${when}] ${who}: ${text}`);
28
- }
29
- return lines.join('\n');
30
- },
31
- };
@@ -1,24 +0,0 @@
1
- import { z } from 'zod';
2
- import type { PosterlyClient } from '../lib/api-client.js';
3
- export declare const getGoogleBusinessReviewLinkTool: {
4
- name: string;
5
- description: string;
6
- inputSchema: z.ZodObject<{
7
- workspace_id: z.ZodOptional<z.ZodString>;
8
- account_id: z.ZodOptional<z.ZodNumber>;
9
- location_id: z.ZodOptional<z.ZodString>;
10
- }, "strip", z.ZodTypeAny, {
11
- workspace_id?: string | undefined;
12
- account_id?: number | undefined;
13
- location_id?: string | undefined;
14
- }, {
15
- workspace_id?: string | undefined;
16
- account_id?: number | undefined;
17
- location_id?: string | undefined;
18
- }>;
19
- execute(client: PosterlyClient, input: {
20
- workspace_id?: string;
21
- account_id?: number;
22
- location_id?: string;
23
- }): Promise<string>;
24
- };
@@ -1,19 +0,0 @@
1
- import { z } from 'zod';
2
- export const getGoogleBusinessReviewLinkTool = {
3
- name: 'get_google_business_review_link',
4
- description: 'Get the direct public Google review link for a connected Google Business Profile location. Requires account_id or location_id. Returns reviewLink plus the Google Place ID (ChIJ...); that Place ID is output only and must NOT be passed back as location_id to other tools.',
5
- inputSchema: z.object({
6
- workspace_id: z.string().optional().describe('Filter to a workspace ID from whoami.'),
7
- account_id: z.number().int().positive().optional().describe('Google Business account ID from list_accounts.'),
8
- location_id: z.string().optional().describe('Google Business numeric location id (the location_id/platform_user_id from list_accounts, e.g. "197940849675145390"). NOT the ChIJ... Place ID this tool returns. Prefer account_id.'),
9
- }),
10
- async execute(client, input) {
11
- const result = await client.getGoogleBusinessReviewLink(input);
12
- return [
13
- `Review link for ${result.businessName}:`,
14
- result.reviewLink,
15
- `Place ID: ${result.placeId}`,
16
- `Account ID: ${result.account_id}`,
17
- ].join('\n');
18
- },
19
- };
@@ -1,24 +0,0 @@
1
- import { z } from 'zod';
2
- import type { PosterlyClient } from '../lib/api-client.js';
3
- export declare const getImageJobTool: {
4
- name: string;
5
- description: string;
6
- inputSchema: z.ZodObject<{
7
- job_id: z.ZodOptional<z.ZodString>;
8
- status: z.ZodOptional<z.ZodEnum<["pending", "processing", "completed", "failed"]>>;
9
- limit: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
10
- }, "strip", z.ZodTypeAny, {
11
- status?: "failed" | "pending" | "completed" | "processing" | undefined;
12
- limit?: number | undefined;
13
- job_id?: string | undefined;
14
- }, {
15
- status?: "failed" | "pending" | "completed" | "processing" | undefined;
16
- limit?: number | undefined;
17
- job_id?: string | undefined;
18
- }>;
19
- execute(client: PosterlyClient, input: {
20
- job_id?: string;
21
- status?: string;
22
- limit?: number;
23
- }): Promise<string>;
24
- };
@@ -1,31 +0,0 @@
1
- import { z } from 'zod';
2
- export const getImageJobTool = {
3
- name: 'get_image_job',
4
- description: 'Get one AI image generation job by ID, or list recent image jobs when job_id is omitted. Use after generate_image to poll for completed urls.',
5
- inputSchema: z.object({
6
- job_id: z.string().optional(),
7
- status: z.enum(['pending', 'processing', 'completed', 'failed']).optional(),
8
- limit: z.number().int().min(1).max(50).default(10).optional(),
9
- }),
10
- async execute(client, input) {
11
- const result = await client.getImageJob(input);
12
- if (result.job)
13
- return formatJob(result.job, true);
14
- const jobs = result.jobs || [];
15
- return [
16
- `Image jobs (${jobs.length})`,
17
- jobs.map((job) => formatJob(job, false)).join('\n\n'),
18
- ].filter(Boolean).join('\n');
19
- },
20
- };
21
- function formatJob(job, includeRaw) {
22
- const lines = [
23
- `${job.id}: ${job.status}`,
24
- `Prompt: ${job.prompt}`,
25
- `Model: ${job.model}; resolution: ${job.resolution}; thinking: ${job.thinking_level || 'n/a'}; cost: ${job.credit_cost}`,
26
- job.urls?.length ? `URLs: ${job.urls.join(', ')}` : null,
27
- job.error_message ? `Error: ${job.error_message}` : null,
28
- includeRaw ? `\nRaw job:\n${JSON.stringify(job, null, 2)}` : null,
29
- ];
30
- return lines.filter(Boolean).join('\n');
31
- }
@@ -1,16 +0,0 @@
1
- import { z } from 'zod';
2
- import type { PosterlyClient } from '../lib/api-client.js';
3
- export declare const getLearnedVoiceTool: {
4
- name: string;
5
- description: string;
6
- inputSchema: z.ZodObject<{
7
- account_id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
8
- }, "strip", z.ZodTypeAny, {
9
- account_id: string | number;
10
- }, {
11
- account_id: string | number;
12
- }>;
13
- execute(client: PosterlyClient, input: {
14
- account_id: string | number;
15
- }): Promise<string>;
16
- };
@@ -1,22 +0,0 @@
1
- import { z } from 'zod';
2
- import { mdLearnedVoice, mdTitle } from '../lib/format.js';
3
- export const getLearnedVoiceTool = {
4
- name: 'get_learned_voice',
5
- description: 'Get the voice posterly has learned from a connected account’s real published captions (the "learned captions" shown on the dashboard). Returns a narrative summary, voice traits, style guidelines, and observed posting habits. Keyed by social account ID (from list_accounts or list_brand_accounts). Returns nothing until the account has enough published posts to learn from. Read-only; this never overwrites the saved brand profile.',
6
- inputSchema: z.object({
7
- account_id: z
8
- .union([z.string(), z.number()])
9
- .describe('The social account ID to inspect (from list_accounts or list_brand_accounts).'),
10
- }),
11
- async execute(client, input) {
12
- const { learned_voice } = await client.getAccountLearnedVoice(input.account_id);
13
- const body = mdLearnedVoice(learned_voice);
14
- if (!body) {
15
- return [
16
- mdTitle('No learned voice yet'),
17
- 'posterly has not learned a voice for this account yet. It learns automatically once the account has enough published posts (the captions are analyzed; the saved brand profile is never overwritten).',
18
- ].join('\n\n');
19
- }
20
- return [mdTitle('Learned voice (from published captions)'), body].join('\n\n');
21
- },
22
- };
@@ -1,8 +0,0 @@
1
- import { z } from 'zod';
2
- import type { PosterlyClient } from '../lib/api-client.js';
3
- export declare const getMcpStatusTool: {
4
- name: string;
5
- description: string;
6
- inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
7
- execute(client: PosterlyClient): Promise<string>;
8
- };