posterly-mcp-server 0.19.8 → 0.19.9

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 (106) hide show
  1. package/README.md +36 -25
  2. package/dist/index.js +64 -72
  3. package/dist/lib/api-client.d.ts +6 -0
  4. package/dist/lib/api-client.js +1 -0
  5. package/dist/lib/format.d.ts +11 -0
  6. package/dist/lib/format.js +51 -0
  7. package/dist/tools/audit-google-business-profile.js +12 -15
  8. package/dist/tools/create-connect-session.d.ts +4 -0
  9. package/dist/tools/create-connect-session.js +24 -17
  10. package/dist/tools/create-oauth-client.js +1 -7
  11. package/dist/tools/create-post.d.ts +52 -39
  12. package/dist/tools/create-post.js +36 -23
  13. package/dist/tools/create-posts-batch.d.ts +36 -29
  14. package/dist/tools/create-posts-batch.js +21 -23
  15. package/dist/tools/create-signed-upload.js +7 -10
  16. package/dist/tools/create-webhook.js +2 -7
  17. package/dist/tools/delete-google-business-review-reply.d.ts +1 -1
  18. package/dist/tools/delete-google-business-review-reply.js +1 -4
  19. package/dist/tools/delete-oauth-client.js +1 -4
  20. package/dist/tools/delete-post-group.js +1 -5
  21. package/dist/tools/delete-post.js +8 -4
  22. package/dist/tools/delete-webhook.js +1 -4
  23. package/dist/tools/disconnect-account.js +5 -7
  24. package/dist/tools/generate-captions.d.ts +2 -2
  25. package/dist/tools/generate-video.js +9 -11
  26. package/dist/tools/get-account-analytics.d.ts +7 -0
  27. package/dist/tools/get-account-analytics.js +116 -54
  28. package/dist/tools/get-connect-link.d.ts +4 -0
  29. package/dist/tools/get-connect-link.js +14 -28
  30. package/dist/tools/get-connect-session.d.ts +4 -0
  31. package/dist/tools/get-connect-session.js +41 -15
  32. package/dist/tools/get-google-business-review-link.js +6 -6
  33. package/dist/tools/get-platform-schema.js +16 -23
  34. package/dist/tools/get-post-analytics.d.ts +7 -0
  35. package/dist/tools/get-post-analytics.js +116 -40
  36. package/dist/tools/get-post-missing.js +1 -5
  37. package/dist/tools/get-post.js +16 -16
  38. package/dist/tools/get-video-job.d.ts +2 -2
  39. package/dist/tools/get-video-job.js +11 -28
  40. package/dist/tools/get-video-options.js +15 -21
  41. package/dist/tools/get-x-posting-quota.js +9 -12
  42. package/dist/tools/list-activity.js +18 -13
  43. package/dist/tools/list-google-business-reviews.js +11 -13
  44. package/dist/tools/list-oauth-clients.js +4 -10
  45. package/dist/tools/list-platforms.js +5 -12
  46. package/dist/tools/list-posts.js +13 -11
  47. package/dist/tools/list-webhooks.js +11 -13
  48. package/dist/tools/reply-google-business-review.d.ts +1 -1
  49. package/dist/tools/reply-google-business-review.js +1 -4
  50. package/dist/tools/run-video-function.js +4 -4
  51. package/dist/tools/suggest-google-business-review-reply.js +4 -5
  52. package/dist/tools/test-webhook.js +1 -7
  53. package/dist/tools/trigger-platform-helper.js +1 -5
  54. package/dist/tools/update-oauth-client.js +1 -8
  55. package/dist/tools/update-post-release-id.js +1 -5
  56. package/dist/tools/update-post-status.d.ts +2 -2
  57. package/dist/tools/update-post-status.js +1 -7
  58. package/dist/tools/update-post.d.ts +20 -20
  59. package/dist/tools/update-webhook.js +1 -7
  60. package/dist/tools/upload-media-from-url.js +9 -7
  61. package/package.json +1 -1
  62. package/src/index.ts +69 -77
  63. package/src/lib/api-client.ts +3 -0
  64. package/src/lib/format.ts +57 -0
  65. package/src/tools/audit-google-business-profile.ts +12 -18
  66. package/src/tools/create-connect-session.ts +25 -18
  67. package/src/tools/create-oauth-client.ts +2 -8
  68. package/src/tools/create-post.ts +40 -23
  69. package/src/tools/create-posts-batch.ts +28 -23
  70. package/src/tools/create-signed-upload.ts +7 -10
  71. package/src/tools/create-webhook.ts +2 -7
  72. package/src/tools/delete-google-business-review-reply.ts +1 -4
  73. package/src/tools/delete-oauth-client.ts +1 -4
  74. package/src/tools/delete-post-group.ts +1 -5
  75. package/src/tools/delete-post.ts +8 -4
  76. package/src/tools/delete-webhook.ts +1 -4
  77. package/src/tools/disconnect-account.ts +5 -7
  78. package/src/tools/generate-video.ts +9 -11
  79. package/src/tools/get-account-analytics.ts +123 -60
  80. package/src/tools/get-connect-link.ts +15 -32
  81. package/src/tools/get-connect-session.ts +43 -16
  82. package/src/tools/get-google-business-review-link.ts +6 -6
  83. package/src/tools/get-platform-schema.ts +16 -29
  84. package/src/tools/get-post-analytics.ts +130 -55
  85. package/src/tools/get-post-missing.ts +1 -5
  86. package/src/tools/get-post.ts +15 -16
  87. package/src/tools/get-video-job.ts +11 -31
  88. package/src/tools/get-video-options.ts +15 -27
  89. package/src/tools/get-x-posting-quota.ts +9 -12
  90. package/src/tools/list-activity.ts +19 -16
  91. package/src/tools/list-google-business-reviews.ts +12 -16
  92. package/src/tools/list-oauth-clients.ts +4 -13
  93. package/src/tools/list-platforms.ts +5 -15
  94. package/src/tools/list-posts.ts +14 -14
  95. package/src/tools/list-webhooks.ts +11 -16
  96. package/src/tools/reply-google-business-review.ts +1 -4
  97. package/src/tools/run-video-function.ts +4 -4
  98. package/src/tools/suggest-google-business-review-reply.ts +4 -5
  99. package/src/tools/test-webhook.ts +1 -7
  100. package/src/tools/trigger-platform-helper.ts +1 -5
  101. package/src/tools/update-oauth-client.ts +2 -9
  102. package/src/tools/update-post-release-id.ts +1 -5
  103. package/src/tools/update-post-status.ts +1 -7
  104. package/src/tools/update-webhook.ts +1 -7
  105. package/src/tools/upload-media-from-url.ts +9 -7
  106. package/src/tools/webhook-events.ts +0 -1
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
@@ -12,35 +14,39 @@ This package gives Claude Desktop, Cursor, Windsurf, Cline, and other local MCP
12
14
  - generate images
13
15
  - read account and post analytics
14
16
 
15
- Tool results are returned as Markdown-first chat summaries with headings, compact tables, short next-step notes, and occasional status icons. MCP clients may still rephrase the final answer, but the raw tool content is designed to look good directly in chat.
16
-
17
- Posterly also exposes the same toolset over HTTP at [poster.ly/mcp](https://www.poster.ly/mcp), but this npm package is the local `stdio` transport.
17
+ Posterly also exposes the same authenticated toolset over HTTP at [poster.ly/mcp](https://www.poster.ly/mcp), but this npm package is the local `stdio` transport.
18
18
 
19
19
  ## Requirements
20
20
 
21
21
  - Node.js `20+`
22
- - A Posterly account: [poster.ly/signup](https://www.poster.ly/signup)
23
- - The Posterly API add-on enabled: [poster.ly/dashboard/api](https://www.poster.ly/dashboard/api)
24
- - A Posterly API key
25
-
26
- No API key is required for the public signup tools: `get_agent_signup_info`, `start_signup`, and `get_signup_session`.
22
+ - No API key is required for the public signup tools: `get_agent_signup_info`, `start_signup`, and `get_signup_session`
23
+ - A Posterly account, API add-on, and API key are required for authenticated tools like `whoami`, `list_accounts`, `create_connect_session`, and `create_post`
27
24
 
28
25
  ## Install
29
26
 
30
- You can install globally:
27
+ Recommended: use it via `npx` in your MCP config so your client runs the current server without a global install.
31
28
 
32
- ```bash
33
- npm install -g posterly-mcp-server
29
+ To let an AI agent start signup before a Posterly API key exists, install the server without `POSTERLY_API_KEY`:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "posterly": {
35
+ "command": "npx",
36
+ "args": ["-y", "posterly-mcp-server@latest"]
37
+ }
38
+ }
39
+ }
34
40
  ```
35
41
 
36
- Or just use it via `npx` in your MCP config:
42
+ After paid signup is complete and Posterly shows an API key, add `POSTERLY_API_KEY` to unlock the authenticated tools:
37
43
 
38
44
  ```json
39
45
  {
40
46
  "mcpServers": {
41
47
  "posterly": {
42
48
  "command": "npx",
43
- "args": ["-y", "posterly-mcp-server"],
49
+ "args": ["-y", "posterly-mcp-server@latest"],
44
50
  "env": {
45
51
  "POSTERLY_API_KEY": "pst_live_your_key_here"
46
52
  }
@@ -51,12 +57,16 @@ Or just use it via `npx` in your MCP config:
51
57
 
52
58
  ## Quick setup
53
59
 
54
- 1. Sign up at [poster.ly](https://www.poster.ly/signup)
55
- 2. Go to [Dashboard API & MCP](https://www.poster.ly/dashboard/api)
56
- 3. Enable the API add-on
57
- 4. Generate an API key
58
- 5. Paste it into your MCP client config as `POSTERLY_API_KEY`
59
- 6. Restart your AI client
60
+ 1. Add the Posterly MCP server to your AI client.
61
+ 2. If you do not have Posterly yet, ask the AI to call `start_signup`.
62
+ 3. Pay in Stripe Checkout and set your Posterly password in the browser.
63
+ 4. When Posterly shows your API key, add it as `POSTERLY_API_KEY`.
64
+ 5. Restart your AI client.
65
+ 6. Ask the AI to call `whoami`, then continue by connecting your first social account.
66
+
67
+ The signup and connect tools return user-facing next steps by default, so agents should report progress in plain language instead of showing raw curl, HTTP payloads, or JSON. Pass `debug: true` to `start_signup`, `get_signup_session`, `get_connect_link`, `create_connect_session`, or `get_connect_session` only when troubleshooting.
68
+
69
+ Post tools return `View in Posterly` dashboard links. After scheduling, listing, reading, or deleting posts, share the returned link with the user. Current-month scheduled posts open in Calendar with the post selected; broader/future post views use Table.
60
70
 
61
71
  ## Example configs
62
72
 
@@ -69,7 +79,7 @@ Add this to your Claude Desktop MCP config:
69
79
  "mcpServers": {
70
80
  "posterly": {
71
81
  "command": "npx",
72
- "args": ["-y", "posterly-mcp-server"],
82
+ "args": ["-y", "posterly-mcp-server@latest"],
73
83
  "env": {
74
84
  "POSTERLY_API_KEY": "pst_live_your_key_here"
75
85
  }
@@ -87,7 +97,7 @@ Add the same server definition to your Cursor MCP settings:
87
97
  "mcpServers": {
88
98
  "posterly": {
89
99
  "command": "npx",
90
- "args": ["-y", "posterly-mcp-server"],
100
+ "args": ["-y", "posterly-mcp-server@latest"],
91
101
  "env": {
92
102
  "POSTERLY_API_KEY": "pst_live_your_key_here"
93
103
  }
@@ -98,15 +108,15 @@ Add the same server definition to your Cursor MCP settings:
98
108
 
99
109
  ## Available tools
100
110
 
101
- `posterly-mcp-server@0.19.8` exposes 55 tools: 3 public signup helpers plus the 52 authenticated API/MCP tools.
111
+ `posterly-mcp-server@0.19.9` exposes 55 tools.
102
112
 
103
- Public signup helpers:
113
+ Public signup tools work before `POSTERLY_API_KEY` exists:
104
114
 
105
115
  - `get_agent_signup_info`
106
116
  - `start_signup` (start paid signup and return a Posterly checkout handoff URL)
107
117
  - `get_signup_session` (poll checkout, payment, password, and agent-access status)
108
118
 
109
- Authenticated tools:
119
+ Authenticated tools require `POSTERLY_API_KEY`:
110
120
 
111
121
  - `whoami`
112
122
  - `list_accounts`
@@ -194,6 +204,7 @@ much more reliable than forcing the agent to guess from raw account handles alon
194
204
  - `Schedule this as an Instagram Story with a first comment and @partner as collaborator`
195
205
  - `Schedule this YouTube video as unlisted, add the thumbnail URL, and put it in our launch playlist`
196
206
  - `Post this TikTok with direct-post privacy set to public and stitch disabled`
207
+ - `Schedule these 5 photos as a TikTok` (image posts auto-detect as a photo slideshow of 1 to 35 images, no post type needed)
197
208
  - `How did Grassroots perform on Instagram in the last 30 days?`
198
209
 
199
210
  ## Pricing
@@ -230,5 +241,5 @@ npm start
230
241
 
231
242
  The package reads:
232
243
 
233
- - `POSTERLY_API_KEY`
244
+ - optional `POSTERLY_API_KEY` for authenticated Posterly tools
234
245
  - optional `POSTERLY_URL` if you need to point at a non-production environment
package/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
- import { mdError } from './lib/format.js';
5
4
  import { PosterlyClient } from './lib/api-client.js';
6
5
  import { getAgentSignupInfoTool } from './tools/get-agent-signup-info.js';
7
6
  import { getSignupSessionTool } from './tools/get-signup-session.js';
@@ -62,14 +61,7 @@ const server = new McpServer({
62
61
  name: 'posterly',
63
62
  version: '0.19.8',
64
63
  });
65
- let client;
66
- try {
67
- client = new PosterlyClient();
68
- }
69
- catch (err) {
70
- console.error(err.message);
71
- process.exit(1);
72
- }
64
+ const client = new PosterlyClient();
73
65
  // Register tools
74
66
  server.tool(getAgentSignupInfoTool.name, getAgentSignupInfoTool.description, getAgentSignupInfoTool.inputSchema.shape, async () => {
75
67
  try {
@@ -77,7 +69,7 @@ server.tool(getAgentSignupInfoTool.name, getAgentSignupInfoTool.description, get
77
69
  return { content: [{ type: 'text', text }] };
78
70
  }
79
71
  catch (err) {
80
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
72
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
81
73
  }
82
74
  });
83
75
  server.tool(startSignupTool.name, startSignupTool.description, startSignupTool.inputSchema.shape, async (input) => {
@@ -86,7 +78,7 @@ server.tool(startSignupTool.name, startSignupTool.description, startSignupTool.i
86
78
  return { content: [{ type: 'text', text }] };
87
79
  }
88
80
  catch (err) {
89
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
81
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
90
82
  }
91
83
  });
92
84
  server.tool(getSignupSessionTool.name, getSignupSessionTool.description, getSignupSessionTool.inputSchema.shape, async (input) => {
@@ -95,7 +87,7 @@ server.tool(getSignupSessionTool.name, getSignupSessionTool.description, getSign
95
87
  return { content: [{ type: 'text', text }] };
96
88
  }
97
89
  catch (err) {
98
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
90
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
99
91
  }
100
92
  });
101
93
  server.tool(whoamiTool.name, whoamiTool.description, whoamiTool.inputSchema.shape, async () => {
@@ -104,7 +96,7 @@ server.tool(whoamiTool.name, whoamiTool.description, whoamiTool.inputSchema.shap
104
96
  return { content: [{ type: 'text', text }] };
105
97
  }
106
98
  catch (err) {
107
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
99
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
108
100
  }
109
101
  });
110
102
  server.tool(listAccountsTool.name, listAccountsTool.description, listAccountsTool.inputSchema.shape, async (input) => {
@@ -113,7 +105,7 @@ server.tool(listAccountsTool.name, listAccountsTool.description, listAccountsToo
113
105
  return { content: [{ type: 'text', text }] };
114
106
  }
115
107
  catch (err) {
116
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
108
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
117
109
  }
118
110
  });
119
111
  server.tool(disconnectAccountTool.name, disconnectAccountTool.description, disconnectAccountTool.inputSchema.shape, async (input) => {
@@ -122,7 +114,7 @@ server.tool(disconnectAccountTool.name, disconnectAccountTool.description, disco
122
114
  return { content: [{ type: 'text', text }] };
123
115
  }
124
116
  catch (err) {
125
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
117
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
126
118
  }
127
119
  });
128
120
  server.tool(getConnectLinkTool.name, getConnectLinkTool.description, getConnectLinkTool.inputSchema.shape, async (input) => {
@@ -131,7 +123,7 @@ server.tool(getConnectLinkTool.name, getConnectLinkTool.description, getConnectL
131
123
  return { content: [{ type: 'text', text }] };
132
124
  }
133
125
  catch (err) {
134
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
126
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
135
127
  }
136
128
  });
137
129
  server.tool(createConnectSessionTool.name, createConnectSessionTool.description, createConnectSessionTool.inputSchema.shape, async (input) => {
@@ -140,7 +132,7 @@ server.tool(createConnectSessionTool.name, createConnectSessionTool.description,
140
132
  return { content: [{ type: 'text', text }] };
141
133
  }
142
134
  catch (err) {
143
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
135
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
144
136
  }
145
137
  });
146
138
  server.tool(getConnectSessionTool.name, getConnectSessionTool.description, getConnectSessionTool.inputSchema.shape, async (input) => {
@@ -149,7 +141,7 @@ server.tool(getConnectSessionTool.name, getConnectSessionTool.description, getCo
149
141
  return { content: [{ type: 'text', text }] };
150
142
  }
151
143
  catch (err) {
152
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
144
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
153
145
  }
154
146
  });
155
147
  server.tool(listOAuthClientsTool.name, listOAuthClientsTool.description, listOAuthClientsTool.inputSchema.shape, async () => {
@@ -158,7 +150,7 @@ server.tool(listOAuthClientsTool.name, listOAuthClientsTool.description, listOAu
158
150
  return { content: [{ type: 'text', text }] };
159
151
  }
160
152
  catch (err) {
161
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
153
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
162
154
  }
163
155
  });
164
156
  server.tool(createOAuthClientTool.name, createOAuthClientTool.description, createOAuthClientTool.inputSchema.shape, async (input) => {
@@ -167,7 +159,7 @@ server.tool(createOAuthClientTool.name, createOAuthClientTool.description, creat
167
159
  return { content: [{ type: 'text', text }] };
168
160
  }
169
161
  catch (err) {
170
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
162
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
171
163
  }
172
164
  });
173
165
  server.tool(updateOAuthClientTool.name, updateOAuthClientTool.description, updateOAuthClientTool.inputSchema.shape, async (input) => {
@@ -176,7 +168,7 @@ server.tool(updateOAuthClientTool.name, updateOAuthClientTool.description, updat
176
168
  return { content: [{ type: 'text', text }] };
177
169
  }
178
170
  catch (err) {
179
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
171
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
180
172
  }
181
173
  });
182
174
  server.tool(deleteOAuthClientTool.name, deleteOAuthClientTool.description, deleteOAuthClientTool.inputSchema.shape, async (input) => {
@@ -185,7 +177,7 @@ server.tool(deleteOAuthClientTool.name, deleteOAuthClientTool.description, delet
185
177
  return { content: [{ type: 'text', text }] };
186
178
  }
187
179
  catch (err) {
188
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
180
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
189
181
  }
190
182
  });
191
183
  server.tool(listPlatformsTool.name, listPlatformsTool.description, listPlatformsTool.inputSchema.shape, async (input) => {
@@ -194,7 +186,7 @@ server.tool(listPlatformsTool.name, listPlatformsTool.description, listPlatforms
194
186
  return { content: [{ type: 'text', text }] };
195
187
  }
196
188
  catch (err) {
197
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
189
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
198
190
  }
199
191
  });
200
192
  server.tool(getPlatformSchemaTool.name, getPlatformSchemaTool.description, getPlatformSchemaTool.inputSchema.shape, async (input) => {
@@ -203,7 +195,7 @@ server.tool(getPlatformSchemaTool.name, getPlatformSchemaTool.description, getPl
203
195
  return { content: [{ type: 'text', text }] };
204
196
  }
205
197
  catch (err) {
206
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
198
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
207
199
  }
208
200
  });
209
201
  server.tool(triggerPlatformHelperTool.name, triggerPlatformHelperTool.description, triggerPlatformHelperTool.inputSchema.shape, async (input) => {
@@ -212,7 +204,7 @@ server.tool(triggerPlatformHelperTool.name, triggerPlatformHelperTool.descriptio
212
204
  return { content: [{ type: 'text', text }] };
213
205
  }
214
206
  catch (err) {
215
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
207
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
216
208
  }
217
209
  });
218
210
  server.tool(listBrandsTool.name, listBrandsTool.description, listBrandsTool.inputSchema.shape, async (input) => {
@@ -221,7 +213,7 @@ server.tool(listBrandsTool.name, listBrandsTool.description, listBrandsTool.inpu
221
213
  return { content: [{ type: 'text', text }] };
222
214
  }
223
215
  catch (err) {
224
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
216
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
225
217
  }
226
218
  });
227
219
  server.tool(getBrandTool.name, getBrandTool.description, getBrandTool.inputSchema.shape, async (input) => {
@@ -230,7 +222,7 @@ server.tool(getBrandTool.name, getBrandTool.description, getBrandTool.inputSchem
230
222
  return { content: [{ type: 'text', text }] };
231
223
  }
232
224
  catch (err) {
233
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
225
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
234
226
  }
235
227
  });
236
228
  server.tool(listBrandAccountsTool.name, listBrandAccountsTool.description, listBrandAccountsTool.inputSchema.shape, async (input) => {
@@ -239,7 +231,7 @@ server.tool(listBrandAccountsTool.name, listBrandAccountsTool.description, listB
239
231
  return { content: [{ type: 'text', text }] };
240
232
  }
241
233
  catch (err) {
242
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
234
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
243
235
  }
244
236
  });
245
237
  server.tool(getBrandProfileTool.name, getBrandProfileTool.description, getBrandProfileTool.inputSchema.shape, async (input) => {
@@ -248,7 +240,7 @@ server.tool(getBrandProfileTool.name, getBrandProfileTool.description, getBrandP
248
240
  return { content: [{ type: 'text', text }] };
249
241
  }
250
242
  catch (err) {
251
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
243
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
252
244
  }
253
245
  });
254
246
  server.tool(createPostTool.name, createPostTool.description, createPostTool.inputSchema.shape, async (input) => {
@@ -257,7 +249,7 @@ server.tool(createPostTool.name, createPostTool.description, createPostTool.inpu
257
249
  return { content: [{ type: 'text', text }] };
258
250
  }
259
251
  catch (err) {
260
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
252
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
261
253
  }
262
254
  });
263
255
  server.tool(createPostsBatchTool.name, createPostsBatchTool.description, createPostsBatchTool.inputSchema.shape, async (input) => {
@@ -266,7 +258,7 @@ server.tool(createPostsBatchTool.name, createPostsBatchTool.description, createP
266
258
  return { content: [{ type: 'text', text }] };
267
259
  }
268
260
  catch (err) {
269
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
261
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
270
262
  }
271
263
  });
272
264
  server.tool(findSlotTool.name, findSlotTool.description, findSlotTool.inputSchema.shape, async (input) => {
@@ -275,7 +267,7 @@ server.tool(findSlotTool.name, findSlotTool.description, findSlotTool.inputSchem
275
267
  return { content: [{ type: 'text', text }] };
276
268
  }
277
269
  catch (err) {
278
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
270
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
279
271
  }
280
272
  });
281
273
  server.tool(listPostsTool.name, listPostsTool.description, listPostsTool.inputSchema.shape, async (input) => {
@@ -284,7 +276,7 @@ server.tool(listPostsTool.name, listPostsTool.description, listPostsTool.inputSc
284
276
  return { content: [{ type: 'text', text }] };
285
277
  }
286
278
  catch (err) {
287
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
279
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
288
280
  }
289
281
  });
290
282
  server.tool(uploadMediaTool.name, uploadMediaTool.description, uploadMediaTool.inputSchema.shape, async (input) => {
@@ -293,7 +285,7 @@ server.tool(uploadMediaTool.name, uploadMediaTool.description, uploadMediaTool.i
293
285
  return { content: [{ type: 'text', text }] };
294
286
  }
295
287
  catch (err) {
296
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
288
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
297
289
  }
298
290
  });
299
291
  server.tool(uploadMediaFromUrlTool.name, uploadMediaFromUrlTool.description, uploadMediaFromUrlTool.inputSchema.shape, async (input) => {
@@ -302,7 +294,7 @@ server.tool(uploadMediaFromUrlTool.name, uploadMediaFromUrlTool.description, upl
302
294
  return { content: [{ type: 'text', text }] };
303
295
  }
304
296
  catch (err) {
305
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
297
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
306
298
  }
307
299
  });
308
300
  server.tool(createSignedUploadTool.name, createSignedUploadTool.description, createSignedUploadTool.inputSchema.shape, async (input) => {
@@ -311,16 +303,7 @@ server.tool(createSignedUploadTool.name, createSignedUploadTool.description, cre
311
303
  return { content: [{ type: 'text', text }] };
312
304
  }
313
305
  catch (err) {
314
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
315
- }
316
- });
317
- server.tool(generateCaptionsTool.name, generateCaptionsTool.description, generateCaptionsTool.inputSchema.shape, async (input) => {
318
- try {
319
- const text = await generateCaptionsTool.execute(client, input);
320
- return { content: [{ type: 'text', text }] };
321
- }
322
- catch (err) {
323
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
306
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
324
307
  }
325
308
  });
326
309
  server.tool(getVideoOptionsTool.name, getVideoOptionsTool.description, getVideoOptionsTool.inputSchema.shape, async () => {
@@ -329,7 +312,7 @@ server.tool(getVideoOptionsTool.name, getVideoOptionsTool.description, getVideoO
329
312
  return { content: [{ type: 'text', text }] };
330
313
  }
331
314
  catch (err) {
332
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
315
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
333
316
  }
334
317
  });
335
318
  server.tool(runVideoFunctionTool.name, runVideoFunctionTool.description, runVideoFunctionTool.inputSchema.shape, async (input) => {
@@ -338,7 +321,7 @@ server.tool(runVideoFunctionTool.name, runVideoFunctionTool.description, runVide
338
321
  return { content: [{ type: 'text', text }] };
339
322
  }
340
323
  catch (err) {
341
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
324
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
342
325
  }
343
326
  });
344
327
  server.tool(generateVideoTool.name, generateVideoTool.description, generateVideoTool.inputSchema.shape, async (input) => {
@@ -347,7 +330,7 @@ server.tool(generateVideoTool.name, generateVideoTool.description, generateVideo
347
330
  return { content: [{ type: 'text', text }] };
348
331
  }
349
332
  catch (err) {
350
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
333
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
351
334
  }
352
335
  });
353
336
  server.tool(getVideoJobTool.name, getVideoJobTool.description, getVideoJobTool.inputSchema.shape, async (input) => {
@@ -356,7 +339,16 @@ server.tool(getVideoJobTool.name, getVideoJobTool.description, getVideoJobTool.i
356
339
  return { content: [{ type: 'text', text }] };
357
340
  }
358
341
  catch (err) {
359
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
342
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
343
+ }
344
+ });
345
+ server.tool(generateCaptionsTool.name, generateCaptionsTool.description, generateCaptionsTool.inputSchema.shape, async (input) => {
346
+ try {
347
+ const text = await generateCaptionsTool.execute(client, input);
348
+ return { content: [{ type: 'text', text }] };
349
+ }
350
+ catch (err) {
351
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
360
352
  }
361
353
  });
362
354
  server.tool(generateImageTool.name, generateImageTool.description, generateImageTool.inputSchema.shape, async (input) => {
@@ -365,7 +357,7 @@ server.tool(generateImageTool.name, generateImageTool.description, generateImage
365
357
  return { content: [{ type: 'text', text }] };
366
358
  }
367
359
  catch (err) {
368
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
360
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
369
361
  }
370
362
  });
371
363
  server.tool(getPostTool.name, getPostTool.description, getPostTool.inputSchema.shape, async (input) => {
@@ -374,7 +366,7 @@ server.tool(getPostTool.name, getPostTool.description, getPostTool.inputSchema.s
374
366
  return { content: [{ type: 'text', text }] };
375
367
  }
376
368
  catch (err) {
377
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
369
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
378
370
  }
379
371
  });
380
372
  server.tool(getPostMissingTool.name, getPostMissingTool.description, getPostMissingTool.inputSchema.shape, async (input) => {
@@ -383,7 +375,7 @@ server.tool(getPostMissingTool.name, getPostMissingTool.description, getPostMiss
383
375
  return { content: [{ type: 'text', text }] };
384
376
  }
385
377
  catch (err) {
386
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
378
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
387
379
  }
388
380
  });
389
381
  server.tool(updatePostTool.name, updatePostTool.description, updatePostTool.inputSchema.shape, async (input) => {
@@ -392,7 +384,7 @@ server.tool(updatePostTool.name, updatePostTool.description, updatePostTool.inpu
392
384
  return { content: [{ type: 'text', text }] };
393
385
  }
394
386
  catch (err) {
395
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
387
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
396
388
  }
397
389
  });
398
390
  server.tool(updatePostStatusTool.name, updatePostStatusTool.description, updatePostStatusTool.inputSchema.shape, async (input) => {
@@ -401,7 +393,7 @@ server.tool(updatePostStatusTool.name, updatePostStatusTool.description, updateP
401
393
  return { content: [{ type: 'text', text }] };
402
394
  }
403
395
  catch (err) {
404
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
396
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
405
397
  }
406
398
  });
407
399
  server.tool(updatePostReleaseIdTool.name, updatePostReleaseIdTool.description, updatePostReleaseIdTool.inputSchema.shape, async (input) => {
@@ -410,7 +402,7 @@ server.tool(updatePostReleaseIdTool.name, updatePostReleaseIdTool.description, u
410
402
  return { content: [{ type: 'text', text }] };
411
403
  }
412
404
  catch (err) {
413
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
405
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
414
406
  }
415
407
  });
416
408
  server.tool(deletePostTool.name, deletePostTool.description, deletePostTool.inputSchema.shape, async (input) => {
@@ -419,7 +411,7 @@ server.tool(deletePostTool.name, deletePostTool.description, deletePostTool.inpu
419
411
  return { content: [{ type: 'text', text }] };
420
412
  }
421
413
  catch (err) {
422
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
414
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
423
415
  }
424
416
  });
425
417
  server.tool(deletePostGroupTool.name, deletePostGroupTool.description, deletePostGroupTool.inputSchema.shape, async (input) => {
@@ -428,7 +420,7 @@ server.tool(deletePostGroupTool.name, deletePostGroupTool.description, deletePos
428
420
  return { content: [{ type: 'text', text }] };
429
421
  }
430
422
  catch (err) {
431
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
423
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
432
424
  }
433
425
  });
434
426
  server.tool(getAccountAnalyticsTool.name, getAccountAnalyticsTool.description, getAccountAnalyticsTool.inputSchema.shape, async (input) => {
@@ -437,7 +429,7 @@ server.tool(getAccountAnalyticsTool.name, getAccountAnalyticsTool.description, g
437
429
  return { content: [{ type: 'text', text }] };
438
430
  }
439
431
  catch (err) {
440
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
432
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
441
433
  }
442
434
  });
443
435
  server.tool(getPostAnalyticsTool.name, getPostAnalyticsTool.description, getPostAnalyticsTool.inputSchema.shape, async (input) => {
@@ -446,7 +438,7 @@ server.tool(getPostAnalyticsTool.name, getPostAnalyticsTool.description, getPost
446
438
  return { content: [{ type: 'text', text }] };
447
439
  }
448
440
  catch (err) {
449
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
441
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
450
442
  }
451
443
  });
452
444
  server.tool(listGoogleBusinessReviewsTool.name, listGoogleBusinessReviewsTool.description, listGoogleBusinessReviewsTool.inputSchema.shape, async (input) => {
@@ -455,7 +447,7 @@ server.tool(listGoogleBusinessReviewsTool.name, listGoogleBusinessReviewsTool.de
455
447
  return { content: [{ type: 'text', text }] };
456
448
  }
457
449
  catch (err) {
458
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
450
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
459
451
  }
460
452
  });
461
453
  server.tool(getGoogleBusinessReviewLinkTool.name, getGoogleBusinessReviewLinkTool.description, getGoogleBusinessReviewLinkTool.inputSchema.shape, async (input) => {
@@ -464,7 +456,7 @@ server.tool(getGoogleBusinessReviewLinkTool.name, getGoogleBusinessReviewLinkToo
464
456
  return { content: [{ type: 'text', text }] };
465
457
  }
466
458
  catch (err) {
467
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
459
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
468
460
  }
469
461
  });
470
462
  server.tool(auditGoogleBusinessProfileTool.name, auditGoogleBusinessProfileTool.description, auditGoogleBusinessProfileTool.inputSchema.shape, async (input) => {
@@ -473,7 +465,7 @@ server.tool(auditGoogleBusinessProfileTool.name, auditGoogleBusinessProfileTool.
473
465
  return { content: [{ type: 'text', text }] };
474
466
  }
475
467
  catch (err) {
476
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
468
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
477
469
  }
478
470
  });
479
471
  server.tool(suggestGoogleBusinessReviewReplyTool.name, suggestGoogleBusinessReviewReplyTool.description, suggestGoogleBusinessReviewReplyTool.inputSchema.shape, async (input) => {
@@ -482,7 +474,7 @@ server.tool(suggestGoogleBusinessReviewReplyTool.name, suggestGoogleBusinessRevi
482
474
  return { content: [{ type: 'text', text }] };
483
475
  }
484
476
  catch (err) {
485
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
477
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
486
478
  }
487
479
  });
488
480
  server.tool(replyGoogleBusinessReviewTool.name, replyGoogleBusinessReviewTool.description, replyGoogleBusinessReviewTool.inputSchema.shape, async (input) => {
@@ -491,7 +483,7 @@ server.tool(replyGoogleBusinessReviewTool.name, replyGoogleBusinessReviewTool.de
491
483
  return { content: [{ type: 'text', text }] };
492
484
  }
493
485
  catch (err) {
494
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
486
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
495
487
  }
496
488
  });
497
489
  server.tool(deleteGoogleBusinessReviewReplyTool.name, deleteGoogleBusinessReviewReplyTool.description, deleteGoogleBusinessReviewReplyTool.inputSchema.shape, async (input) => {
@@ -500,7 +492,7 @@ server.tool(deleteGoogleBusinessReviewReplyTool.name, deleteGoogleBusinessReview
500
492
  return { content: [{ type: 'text', text }] };
501
493
  }
502
494
  catch (err) {
503
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
495
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
504
496
  }
505
497
  });
506
498
  server.tool(listActivityTool.name, listActivityTool.description, listActivityTool.inputSchema.shape, async (input) => {
@@ -509,7 +501,7 @@ server.tool(listActivityTool.name, listActivityTool.description, listActivityToo
509
501
  return { content: [{ type: 'text', text }] };
510
502
  }
511
503
  catch (err) {
512
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
504
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
513
505
  }
514
506
  });
515
507
  server.tool(listWebhooksTool.name, listWebhooksTool.description, listWebhooksTool.inputSchema.shape, async (input) => {
@@ -518,7 +510,7 @@ server.tool(listWebhooksTool.name, listWebhooksTool.description, listWebhooksToo
518
510
  return { content: [{ type: 'text', text }] };
519
511
  }
520
512
  catch (err) {
521
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
513
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
522
514
  }
523
515
  });
524
516
  server.tool(createWebhookTool.name, createWebhookTool.description, createWebhookTool.inputSchema.shape, async (input) => {
@@ -527,7 +519,7 @@ server.tool(createWebhookTool.name, createWebhookTool.description, createWebhook
527
519
  return { content: [{ type: 'text', text }] };
528
520
  }
529
521
  catch (err) {
530
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
522
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
531
523
  }
532
524
  });
533
525
  server.tool(updateWebhookTool.name, updateWebhookTool.description, updateWebhookTool.inputSchema.shape, async (input) => {
@@ -536,7 +528,7 @@ server.tool(updateWebhookTool.name, updateWebhookTool.description, updateWebhook
536
528
  return { content: [{ type: 'text', text }] };
537
529
  }
538
530
  catch (err) {
539
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
531
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
540
532
  }
541
533
  });
542
534
  server.tool(deleteWebhookTool.name, deleteWebhookTool.description, deleteWebhookTool.inputSchema.shape, async (input) => {
@@ -545,7 +537,7 @@ server.tool(deleteWebhookTool.name, deleteWebhookTool.description, deleteWebhook
545
537
  return { content: [{ type: 'text', text }] };
546
538
  }
547
539
  catch (err) {
548
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
540
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
549
541
  }
550
542
  });
551
543
  server.tool(testWebhookTool.name, testWebhookTool.description, testWebhookTool.inputSchema.shape, async (input) => {
@@ -554,7 +546,7 @@ server.tool(testWebhookTool.name, testWebhookTool.description, testWebhookTool.i
554
546
  return { content: [{ type: 'text', text }] };
555
547
  }
556
548
  catch (err) {
557
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
549
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
558
550
  }
559
551
  });
560
552
  server.tool(getXPostingQuotaTool.name, getXPostingQuotaTool.description, getXPostingQuotaTool.inputSchema.shape, async (input) => {
@@ -563,7 +555,7 @@ server.tool(getXPostingQuotaTool.name, getXPostingQuotaTool.description, getXPos
563
555
  return { content: [{ type: 'text', text }] };
564
556
  }
565
557
  catch (err) {
566
- return { content: [{ type: 'text', text: mdError(err.message) }], isError: true };
558
+ return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
567
559
  }
568
560
  });
569
561
  // Start the server
@@ -193,6 +193,12 @@ export interface AccountAnalyticsSummary {
193
193
  total_watch_minutes?: number | null;
194
194
  total_likes?: number | null;
195
195
  platform_metrics?: Record<string, number | null | undefined>;
196
+ display_metrics?: Array<{
197
+ key?: string;
198
+ label: string;
199
+ value: number | null | undefined;
200
+ unit?: string;
201
+ }>;
196
202
  }
197
203
  export interface AccountAnalyticsSnapshot {
198
204
  date: string;