posterly-mcp-server 0.19.5 → 0.19.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,6 +4,8 @@ Use Posterly from any MCP-compatible AI client.
4
4
 
5
5
  This package gives Claude Desktop, Cursor, Windsurf, Cline, and other local MCP clients a `stdio` server that can:
6
6
 
7
+ - start paid Posterly signup before an API key exists
8
+ - poll signup progress while the user completes checkout and password setup
7
9
  - list connected social accounts
8
10
  - resolve brands/clients into the right accounts
9
11
  - schedule and manage posts
@@ -16,26 +18,34 @@ Posterly also exposes the same toolset over HTTP at [poster.ly/mcp](https://www.
16
18
  ## Requirements
17
19
 
18
20
  - Node.js `20+`
19
- - A Posterly account: [poster.ly/signup](https://www.poster.ly/signup)
20
- - The Posterly API add-on enabled: [poster.ly/dashboard/api](https://www.poster.ly/dashboard/api)
21
- - A Posterly API key
21
+ - No API key is required for the public signup tools: `get_agent_signup_info`, `start_signup`, and `get_signup_session`
22
+ - A Posterly account, API add-on, and API key are required for authenticated tools like `whoami`, `list_accounts`, `create_connect_session`, and `create_post`
22
23
 
23
24
  ## Install
24
25
 
25
- You can install globally:
26
+ Recommended: use it via `npx` in your MCP config so your client runs the current server without a global install.
26
27
 
27
- ```bash
28
- npm install -g posterly-mcp-server
28
+ To let an AI agent start signup before a Posterly API key exists, install the server without `POSTERLY_API_KEY`:
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "posterly": {
34
+ "command": "npx",
35
+ "args": ["-y", "posterly-mcp-server@latest"]
36
+ }
37
+ }
38
+ }
29
39
  ```
30
40
 
31
- Or just use it via `npx` in your MCP config:
41
+ After paid signup is complete and Posterly shows an API key, add `POSTERLY_API_KEY` to unlock the authenticated tools:
32
42
 
33
43
  ```json
34
44
  {
35
45
  "mcpServers": {
36
46
  "posterly": {
37
47
  "command": "npx",
38
- "args": ["-y", "posterly-mcp-server"],
48
+ "args": ["-y", "posterly-mcp-server@latest"],
39
49
  "env": {
40
50
  "POSTERLY_API_KEY": "pst_live_your_key_here"
41
51
  }
@@ -46,12 +56,12 @@ Or just use it via `npx` in your MCP config:
46
56
 
47
57
  ## Quick setup
48
58
 
49
- 1. Sign up at [poster.ly](https://www.poster.ly/signup)
50
- 2. Go to [Dashboard API & MCP](https://www.poster.ly/dashboard/api)
51
- 3. Enable the API add-on
52
- 4. Generate an API key
53
- 5. Paste it into your MCP client config as `POSTERLY_API_KEY`
54
- 6. Restart your AI client
59
+ 1. Add the Posterly MCP server to your AI client.
60
+ 2. If you do not have Posterly yet, ask the AI to call `start_signup`.
61
+ 3. Pay in Stripe Checkout and set your Posterly password in the browser.
62
+ 4. When Posterly shows your API key, add it as `POSTERLY_API_KEY`.
63
+ 5. Restart your AI client.
64
+ 6. Ask the AI to call `whoami`, then continue by connecting your first social account.
55
65
 
56
66
  ## Example configs
57
67
 
@@ -64,7 +74,7 @@ Add this to your Claude Desktop MCP config:
64
74
  "mcpServers": {
65
75
  "posterly": {
66
76
  "command": "npx",
67
- "args": ["-y", "posterly-mcp-server"],
77
+ "args": ["-y", "posterly-mcp-server@latest"],
68
78
  "env": {
69
79
  "POSTERLY_API_KEY": "pst_live_your_key_here"
70
80
  }
@@ -82,7 +92,7 @@ Add the same server definition to your Cursor MCP settings:
82
92
  "mcpServers": {
83
93
  "posterly": {
84
94
  "command": "npx",
85
- "args": ["-y", "posterly-mcp-server"],
95
+ "args": ["-y", "posterly-mcp-server@latest"],
86
96
  "env": {
87
97
  "POSTERLY_API_KEY": "pst_live_your_key_here"
88
98
  }
@@ -93,12 +103,22 @@ Add the same server definition to your Cursor MCP settings:
93
103
 
94
104
  ## Available tools
95
105
 
96
- `posterly-mcp-server@0.19.5` exposes 49 tools:
106
+ `posterly-mcp-server@0.19.6` exposes 54 tools.
107
+
108
+ Public signup tools work before `POSTERLY_API_KEY` exists:
109
+
110
+ - `get_agent_signup_info`
111
+ - `start_signup` (start paid signup and return a Posterly checkout handoff URL)
112
+ - `get_signup_session` (poll checkout, payment, password, and agent-access status)
113
+
114
+ Authenticated tools require `POSTERLY_API_KEY`:
97
115
 
98
116
  - `whoami`
99
117
  - `list_accounts`
100
118
  - `disconnect_account` (disconnect a connected social account after explicit confirmation)
101
119
  - `get_connect_link`
120
+ - `create_connect_session` (create a guided browser handoff for connecting a social account)
121
+ - `get_connect_session` (poll connection progress while the user approves OAuth or enters credentials)
102
122
  - `list_oauth_clients`
103
123
  - `create_oauth_client` (create a public PKCE client after explicit confirmation)
104
124
  - `update_oauth_client` (update redirect URIs/scopes after explicit confirmation)
@@ -214,5 +234,5 @@ npm start
214
234
 
215
235
  The package reads:
216
236
 
217
- - `POSTERLY_API_KEY`
237
+ - optional `POSTERLY_API_KEY` for authenticated Posterly tools
218
238
  - optional `POSTERLY_URL` if you need to point at a non-production environment
package/dist/index.js CHANGED
@@ -2,6 +2,9 @@
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { PosterlyClient } from './lib/api-client.js';
5
+ import { getAgentSignupInfoTool } from './tools/get-agent-signup-info.js';
6
+ import { getSignupSessionTool } from './tools/get-signup-session.js';
7
+ import { startSignupTool } from './tools/start-signup.js';
5
8
  import { listAccountsTool } from './tools/list-accounts.js';
6
9
  import { disconnectAccountTool } from './tools/disconnect-account.js';
7
10
  import { listBrandsTool } from './tools/list-brands.js';
@@ -47,23 +50,45 @@ import { getXPostingQuotaTool } from './tools/get-x-posting-quota.js';
47
50
  import { createSignedUploadTool } from './tools/create-signed-upload.js';
48
51
  import { uploadMediaFromUrlTool } from './tools/upload-media-from-url.js';
49
52
  import { getConnectLinkTool } from './tools/get-connect-link.js';
53
+ import { createConnectSessionTool } from './tools/create-connect-session.js';
54
+ import { getConnectSessionTool } from './tools/get-connect-session.js';
50
55
  import { listOAuthClientsTool } from './tools/list-oauth-clients.js';
51
56
  import { createOAuthClientTool } from './tools/create-oauth-client.js';
52
57
  import { updateOAuthClientTool } from './tools/update-oauth-client.js';
53
58
  import { deleteOAuthClientTool } from './tools/delete-oauth-client.js';
54
59
  const server = new McpServer({
55
60
  name: 'posterly',
56
- version: '0.19.0',
61
+ version: '0.19.6',
57
62
  });
58
- let client;
59
- try {
60
- client = new PosterlyClient();
61
- }
62
- catch (err) {
63
- console.error(err.message);
64
- process.exit(1);
65
- }
63
+ const client = new PosterlyClient();
66
64
  // Register tools
65
+ server.tool(getAgentSignupInfoTool.name, getAgentSignupInfoTool.description, getAgentSignupInfoTool.inputSchema.shape, async () => {
66
+ try {
67
+ const text = await getAgentSignupInfoTool.execute(client);
68
+ return { content: [{ type: 'text', text }] };
69
+ }
70
+ catch (err) {
71
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
72
+ }
73
+ });
74
+ server.tool(startSignupTool.name, startSignupTool.description, startSignupTool.inputSchema.shape, async (input) => {
75
+ try {
76
+ const text = await startSignupTool.execute(client, input);
77
+ return { content: [{ type: 'text', text }] };
78
+ }
79
+ catch (err) {
80
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
81
+ }
82
+ });
83
+ server.tool(getSignupSessionTool.name, getSignupSessionTool.description, getSignupSessionTool.inputSchema.shape, async (input) => {
84
+ try {
85
+ const text = await getSignupSessionTool.execute(client, input);
86
+ return { content: [{ type: 'text', text }] };
87
+ }
88
+ catch (err) {
89
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
90
+ }
91
+ });
67
92
  server.tool(whoamiTool.name, whoamiTool.description, whoamiTool.inputSchema.shape, async () => {
68
93
  try {
69
94
  const text = await whoamiTool.execute(client);
@@ -100,6 +125,24 @@ server.tool(getConnectLinkTool.name, getConnectLinkTool.description, getConnectL
100
125
  return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
101
126
  }
102
127
  });
128
+ server.tool(createConnectSessionTool.name, createConnectSessionTool.description, createConnectSessionTool.inputSchema.shape, async (input) => {
129
+ try {
130
+ const text = await createConnectSessionTool.execute(client, input);
131
+ return { content: [{ type: 'text', text }] };
132
+ }
133
+ catch (err) {
134
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
135
+ }
136
+ });
137
+ server.tool(getConnectSessionTool.name, getConnectSessionTool.description, getConnectSessionTool.inputSchema.shape, async (input) => {
138
+ try {
139
+ const text = await getConnectSessionTool.execute(client, input);
140
+ return { content: [{ type: 'text', text }] };
141
+ }
142
+ catch (err) {
143
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
144
+ }
145
+ });
103
146
  server.tool(listOAuthClientsTool.name, listOAuthClientsTool.description, listOAuthClientsTool.inputSchema.shape, async () => {
104
147
  try {
105
148
  const text = await listOAuthClientsTool.execute(client);
@@ -348,6 +348,26 @@ export interface ConnectOption {
348
348
  connected_count?: number;
349
349
  connected_accounts?: Account[];
350
350
  }
351
+ export interface ConnectSession {
352
+ id: string;
353
+ platform: string;
354
+ method: 'dashboard_oauth' | 'manual_credentials';
355
+ status: 'created' | 'opened' | 'awaiting_provider' | 'awaiting_credentials' | 'connected' | 'failed' | 'cancelled' | 'expired';
356
+ status_message: string;
357
+ connect_url: string;
358
+ poll_url: string;
359
+ workspace_id?: string | null;
360
+ connected_account_ids: string[];
361
+ connected_accounts: Account[];
362
+ connected_count: number;
363
+ error_code?: string | null;
364
+ error_message?: string | null;
365
+ created_at: string;
366
+ opened_at?: string | null;
367
+ provider_redirected_at?: string | null;
368
+ completed_at?: string | null;
369
+ expires_at: string;
370
+ }
351
371
  export interface OAuthDeveloperClient {
352
372
  id: string;
353
373
  client_id: string;
@@ -360,6 +380,55 @@ export interface OAuthDeveloperClient {
360
380
  created_at?: string;
361
381
  updated_at?: string;
362
382
  }
383
+ export type PublicSignupTier = 'starter' | 'pro' | 'power_user' | 'agency';
384
+ export interface PublicSignupPayload {
385
+ email: string;
386
+ name?: string;
387
+ tier?: PublicSignupTier;
388
+ interval?: 'month';
389
+ api_addon?: boolean;
390
+ return_path?: string;
391
+ source?: string;
392
+ }
393
+ export interface PublicSignupSession {
394
+ id: string;
395
+ status: string;
396
+ status_message?: string;
397
+ next_action?: {
398
+ actor?: string;
399
+ type?: string;
400
+ label?: string;
401
+ description?: string;
402
+ };
403
+ agent_next_steps?: string[];
404
+ checkout_redirect_url?: string | null;
405
+ checkout?: Record<string, unknown>;
406
+ account?: Record<string, unknown>;
407
+ billing?: Record<string, unknown>;
408
+ links?: Record<string, unknown>;
409
+ created_at?: string;
410
+ updated_at?: string;
411
+ expires_at?: string;
412
+ [key: string]: unknown;
413
+ }
414
+ export interface PublicSignupResponse {
415
+ signup_session?: PublicSignupSession;
416
+ checkout_session_id?: string;
417
+ checkout_url?: string | null;
418
+ checkout_redirect_url?: string | null;
419
+ poll_url?: string | null;
420
+ complete_url?: string | null;
421
+ dashboard_url?: string | null;
422
+ status?: string;
423
+ status_message?: string;
424
+ links?: Record<string, unknown>;
425
+ account?: Record<string, unknown>;
426
+ billing?: Record<string, unknown>;
427
+ [key: string]: unknown;
428
+ }
429
+ export interface PublicSignupSessionResponse {
430
+ signup_session: PublicSignupSession;
431
+ }
363
432
  export interface VideoJob {
364
433
  id: string;
365
434
  status: string;
@@ -401,7 +470,12 @@ export declare class PosterlyClient {
401
470
  private baseUrl;
402
471
  private apiKey;
403
472
  constructor(apiKey?: string, baseUrl?: string);
473
+ hasApiKey(): boolean;
474
+ private requireApiKey;
404
475
  private request;
476
+ private publicRequest;
477
+ startSignup(data: PublicSignupPayload): Promise<PublicSignupResponse>;
478
+ getSignupSession(sessionId: string): Promise<PublicSignupSessionResponse>;
405
479
  whoami(): Promise<Whoami>;
406
480
  listAccounts(params?: {
407
481
  workspace_id?: string;
@@ -415,6 +489,17 @@ export declare class PosterlyClient {
415
489
  connect?: ConnectOption;
416
490
  connect_options?: ConnectOption[];
417
491
  }>;
492
+ createConnectSession(data: {
493
+ platform: string;
494
+ workspace_id?: string;
495
+ auto_start?: boolean;
496
+ }): Promise<{
497
+ connect_session: ConnectSession;
498
+ connect?: ConnectOption;
499
+ }>;
500
+ getConnectSession(sessionId: string): Promise<{
501
+ connect_session: ConnectSession;
502
+ }>;
418
503
  listOAuthClients(): Promise<{
419
504
  clients: OAuthDeveloperClient[];
420
505
  }>;
@@ -6,11 +6,17 @@ export class PosterlyClient {
6
6
  constructor(apiKey, baseUrl) {
7
7
  this.apiKey = apiKey || process.env.POSTERLY_API_KEY || '';
8
8
  this.baseUrl = (baseUrl || process.env.POSTERLY_URL || 'https://www.poster.ly').replace(/\/$/, '');
9
+ }
10
+ hasApiKey() {
11
+ return Boolean(this.apiKey);
12
+ }
13
+ requireApiKey() {
9
14
  if (!this.apiKey) {
10
- throw new Error('POSTERLY_API_KEY is required. Set it as an environment variable.');
15
+ throw new Error('Posterly access is not installed yet. Use start_signup to begin paid setup, or set POSTERLY_API_KEY after signup.');
11
16
  }
12
17
  }
13
18
  async request(method, path, body) {
19
+ this.requireApiKey();
14
20
  const url = `${this.baseUrl}/api/v1${path}`;
15
21
  const headers = {
16
22
  Authorization: `Bearer ${this.apiKey}`,
@@ -30,6 +36,27 @@ export class PosterlyClient {
30
36
  }
31
37
  return res.json();
32
38
  }
39
+ async publicRequest(method, path, body) {
40
+ const url = `${this.baseUrl}${path}`;
41
+ const headers = {};
42
+ const init = { method, headers };
43
+ if (body) {
44
+ headers['Content-Type'] = 'application/json';
45
+ init.body = JSON.stringify(body);
46
+ }
47
+ const res = await fetch(url, init);
48
+ if (!res.ok) {
49
+ const err = await res.json().catch(() => ({ error: res.statusText }));
50
+ throw new Error(err.error || `API error: ${res.status}`);
51
+ }
52
+ return res.json();
53
+ }
54
+ async startSignup(data) {
55
+ return this.publicRequest('POST', '/api/v1/signup', data);
56
+ }
57
+ async getSignupSession(sessionId) {
58
+ return this.publicRequest('GET', `/api/v1/signup/sessions/${encodeURIComponent(sessionId)}`);
59
+ }
33
60
  async whoami() {
34
61
  return this.request('GET', '/whoami');
35
62
  }
@@ -56,6 +83,13 @@ export class PosterlyClient {
56
83
  : '/connect';
57
84
  return this.request('GET', `${path}${qs ? `?${qs}` : ''}`);
58
85
  }
86
+ async createConnectSession(data) {
87
+ const { platform, ...body } = data;
88
+ return this.request('POST', `/connect/${encodeURIComponent(platform)}/sessions`, body);
89
+ }
90
+ async getConnectSession(sessionId) {
91
+ return this.request('GET', `/connect/sessions/${encodeURIComponent(sessionId)}`);
92
+ }
59
93
  async listOAuthClients() {
60
94
  return this.request('GET', '/oauth/clients');
61
95
  }
@@ -304,6 +338,7 @@ export class PosterlyClient {
304
338
  });
305
339
  }
306
340
  async uploadMedia(input) {
341
+ this.requireApiKey();
307
342
  let fileBuffer;
308
343
  if (input.filePath) {
309
344
  fileBuffer = await readFile(resolve(input.filePath));
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ import type { PosterlyClient } from '../lib/api-client.js';
3
+ export declare const createConnectSessionTool: {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: z.ZodObject<{
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
+ workspace_id: z.ZodOptional<z.ZodString>;
9
+ auto_start: z.ZodOptional<z.ZodBoolean>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ 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
+ workspace_id?: string | undefined;
13
+ auto_start?: boolean | undefined;
14
+ }, {
15
+ 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
+ workspace_id?: string | undefined;
17
+ auto_start?: boolean | undefined;
18
+ }>;
19
+ execute(client: PosterlyClient, input: {
20
+ platform: string;
21
+ workspace_id?: string;
22
+ auto_start?: boolean;
23
+ }): Promise<string>;
24
+ };
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ import { CONNECT_INPUTS } from '../generated/platform-manifest.js';
3
+ export const createConnectSessionTool = {
4
+ 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
+ inputSchema: z.object({
7
+ platform: z
8
+ .enum(CONNECT_INPUTS)
9
+ .describe('Connection target such as instagram, meta, linkedin_page, twitter, google_business, telegram, or bluesky.'),
10
+ workspace_id: z
11
+ .string()
12
+ .optional()
13
+ .describe('Workspace to connect the account into. Workspace-scoped API keys ignore this.'),
14
+ auto_start: z
15
+ .boolean()
16
+ .optional()
17
+ .describe('When true, the dashboard starts the provider flow after the user opens the URL. Defaults to true.'),
18
+ }),
19
+ async execute(client, input) {
20
+ const result = await client.createConnectSession(input);
21
+ return formatConnectSession(result.connect_session, true);
22
+ },
23
+ };
24
+ function formatConnectSession(session, includeRaw) {
25
+ return [
26
+ `Posterly connect session: ${session.id}`,
27
+ `Platform: ${session.platform}`,
28
+ `Status: ${session.status}`,
29
+ `Message: ${session.status_message}`,
30
+ `Connection URL: ${session.connect_url}`,
31
+ `Poll URL: ${session.poll_url}`,
32
+ `Connected accounts: ${session.connected_count ?? session.connected_accounts?.length ?? 0}`,
33
+ `Expires: ${session.expires_at}`,
34
+ '',
35
+ 'Next step: Open the connection URL for the user, then call get_connect_session with this session ID until the status is terminal.',
36
+ includeRaw ? `\nRaw connect session:\n${JSON.stringify(session, null, 2)}` : '',
37
+ ].filter(Boolean).join('\n');
38
+ }
@@ -14,15 +14,15 @@ export declare const createWebhookTool: {
14
14
  url: string;
15
15
  confirm: true;
16
16
  workspace_id?: string | undefined;
17
- events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced")[] | undefined;
18
17
  description?: string | undefined;
18
+ events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced")[] | undefined;
19
19
  is_active?: boolean | undefined;
20
20
  }, {
21
21
  url: string;
22
22
  confirm: true;
23
23
  workspace_id?: string | undefined;
24
- events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced")[] | undefined;
25
24
  description?: string | undefined;
25
+ events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced")[] | undefined;
26
26
  is_active?: boolean | undefined;
27
27
  }>;
28
28
  execute(client: PosterlyClient, input: {
@@ -15,14 +15,14 @@ export declare const generateImageTool: {
15
15
  aspect_ratio?: "16:9" | "9:16" | "1:1" | "4:5" | "3:4" | "2:3" | "1:4" | "1:8" | "21:9" | "4:3" | "3:2" | "4:1" | "8:1" | "5:4" | undefined;
16
16
  style?: "professional" | "photographic" | "illustration" | "minimal" | "vibrant" | "youtube_thumbnail" | "reel_cover" | "review_background" | undefined;
17
17
  variations?: number | undefined;
18
- model?: "flash" | "pro" | undefined;
18
+ model?: "pro" | "flash" | undefined;
19
19
  resolution?: "512" | "1K" | "2K" | "4K" | undefined;
20
20
  }, {
21
21
  prompt: string;
22
22
  aspect_ratio?: "16:9" | "9:16" | "1:1" | "4:5" | "3:4" | "2:3" | "1:4" | "1:8" | "21:9" | "4:3" | "3:2" | "4:1" | "8:1" | "5:4" | undefined;
23
23
  style?: "professional" | "photographic" | "illustration" | "minimal" | "vibrant" | "youtube_thumbnail" | "reel_cover" | "review_background" | undefined;
24
24
  variations?: number | undefined;
25
- model?: "flash" | "pro" | undefined;
25
+ model?: "pro" | "flash" | undefined;
26
26
  resolution?: "512" | "1K" | "2K" | "4K" | undefined;
27
27
  }>;
28
28
  execute(client: PosterlyClient, input: {
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ import type { PosterlyClient } from '../lib/api-client.js';
3
+ export declare const getAgentSignupInfoTool: {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
7
+ execute(client: PosterlyClient): Promise<string>;
8
+ };
@@ -0,0 +1,32 @@
1
+ import { z } from 'zod';
2
+ export const getAgentSignupInfoTool = {
3
+ name: 'get_agent_signup_info',
4
+ description: 'Explain how to use Posterly MCP for agent-led signup before an API key exists, including the safe human-in-the-browser boundaries.',
5
+ inputSchema: z.object({}),
6
+ async execute(client) {
7
+ const authState = client.hasApiKey()
8
+ ? 'Posterly API key is installed. Authenticated scheduling and connect tools are available.'
9
+ : 'No Posterly API key is installed. Only public signup tools are available until the user completes paid setup and gives this AI Posterly access.';
10
+ return [
11
+ 'Posterly agent signup info',
12
+ '',
13
+ authState,
14
+ '',
15
+ 'Pre-auth tools:',
16
+ '- start_signup: starts paid signup and returns a Posterly checkout handoff URL plus a signup poll URL.',
17
+ '- get_signup_session: polls checkout, payment, password, and agent-access status.',
18
+ '',
19
+ 'After Posterly access is installed:',
20
+ '- whoami: confirm the paid Posterly account/workspace.',
21
+ '- create_connect_session: create a secure browser OAuth handoff for the social platform the user chooses.',
22
+ '- get_connect_session: poll the OAuth handoff until connected.',
23
+ '- create_post: schedule posts after the user confirms the account and content.',
24
+ '',
25
+ 'Boundaries:',
26
+ '- The user pays in Stripe Checkout in their browser.',
27
+ '- The user sets their Posterly password in their browser.',
28
+ '- The user approves social OAuth in their browser.',
29
+ '- The AI should never ask for card details, Posterly passwords, social passwords, or OAuth codes.',
30
+ ].join('\n');
31
+ },
32
+ };
@@ -0,0 +1,16 @@
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
+ }, "strip", z.ZodTypeAny, {
9
+ session_id: string;
10
+ }, {
11
+ session_id: string;
12
+ }>;
13
+ execute(client: PosterlyClient, input: {
14
+ session_id: string;
15
+ }): Promise<string>;
16
+ };
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ export const getConnectSessionTool = {
3
+ name: 'get_connect_session',
4
+ description: 'Poll a Posterly connect session. Read status_message to tell the user what is happening; stop when status is connected, failed, cancelled, or expired.',
5
+ inputSchema: z.object({
6
+ session_id: z.string().describe('Connect session ID returned by create_connect_session.'),
7
+ }),
8
+ async execute(client, input) {
9
+ const result = await client.getConnectSession(input.session_id);
10
+ return formatConnectSession(result.connect_session);
11
+ },
12
+ };
13
+ function formatConnectSession(session) {
14
+ const connected = session.connected_count ?? session.connected_accounts?.length ?? 0;
15
+ return [
16
+ `Posterly connect session: ${session.id}`,
17
+ `Platform: ${session.platform}`,
18
+ `Status: ${session.status}`,
19
+ `Message: ${session.status_message}`,
20
+ `Connected accounts: ${connected}`,
21
+ session.error_message ? `Error: ${session.error_message}` : '',
22
+ `Expires: ${session.expires_at}`,
23
+ '',
24
+ `Raw connect session:\n${JSON.stringify(session, null, 2)}`,
25
+ ].filter(Boolean).join('\n');
26
+ }
@@ -0,0 +1,16 @@
1
+ import { z } from 'zod';
2
+ import type { PosterlyClient } from '../lib/api-client.js';
3
+ export declare const getSignupSessionTool: {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: z.ZodObject<{
7
+ session_id: z.ZodString;
8
+ }, "strip", z.ZodTypeAny, {
9
+ session_id: string;
10
+ }, {
11
+ session_id: string;
12
+ }>;
13
+ execute(client: PosterlyClient, input: {
14
+ session_id: string;
15
+ }): Promise<string>;
16
+ };