posterly-mcp-server 0.19.1 → 0.19.3

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.
@@ -318,7 +318,7 @@ export class PosterlyClient {
318
318
  guessContentType(input.filename);
319
319
  const SIZE_THRESHOLD = 3 * 1024 * 1024; // 3MB
320
320
  if (fileBuffer.length > SIZE_THRESHOLD) {
321
- // Large file: use signed URL to upload directly to Supabase Storage
321
+ // Large file: use signed URL so the API can validate actual bytes before storage.
322
322
  const signed = await this.getSignedUploadUrl(input.filename, contentType, fileBuffer.length);
323
323
  const uploadRes = await fetch(signed.upload_url, {
324
324
  method: 'PUT',
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  export const createSignedUploadTool = {
3
3
  name: 'create_signed_upload',
4
- description: 'Create a signed direct-upload URL for a larger image or video. Upload the binary to upload_url, then use public_url with create_post.',
4
+ description: 'Create a signed upload URL for a larger image or video. Upload the binary to upload_url; the API validates actual bytes before storage, then public_url can be used with create_post.',
5
5
  inputSchema: z.object({
6
6
  filename: z.string().describe('Filename with extension, e.g. launch-video.mp4'),
7
7
  content_type: z.string().describe('MIME type, e.g. video/mp4'),
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  export const getAccountAnalyticsTool = {
3
3
  name: 'get_account_analytics',
4
- description: 'Get daily analytics snapshots and a period summary for a connected social account. Supports Instagram, Facebook, LinkedIn, Google Business Profile, Pinterest, and YouTube. Returns follower growth, reach, views, engagement rate, and platform-specific metrics.',
4
+ description: 'Get daily analytics snapshots and a period summary for a connected social account. Supports Instagram, Facebook, LinkedIn, Google Business Profile, Pinterest, and YouTube. For Google Business Profile, returns Profile Views, Search Views, Maps Views, Customer Actions, and Posts.',
5
5
  inputSchema: z.object({
6
6
  account_id: z
7
7
  .number()
@@ -18,25 +18,22 @@ export const getAccountAnalyticsTool = {
18
18
  async execute(client, input) {
19
19
  const result = await client.getAccountAnalytics(input);
20
20
  const { account, range, summary, snapshots } = result;
21
+ const accountLabel = account.platform === 'google_business'
22
+ ? `${account.username} (Google Business, id ${account.id})`
23
+ : `@${account.username} (${account.platform}, id ${account.id})`;
21
24
  const lines = [
22
- `Analytics for @${account.username} (${account.platform}, id ${account.id})`,
25
+ `Analytics for ${accountLabel}`,
23
26
  `Range: ${range.from} → ${range.to} (${snapshots.length} daily snapshots)`,
24
27
  '',
25
28
  'Summary:',
26
29
  ];
27
30
  if (account.platform === 'google_business') {
28
31
  const metrics = summary.platform_metrics || {};
29
- pushMetric(lines, 'Profile views', metrics.profile_views ?? summary.total_views);
30
- pushMetric(lines, 'Search views', metrics.search_views ?? summary.total_reach);
31
- pushMetric(lines, 'Maps views', metrics.maps_views ?? summary.total_profile_views);
32
- pushMetric(lines, 'Customer actions', metrics.customer_actions ?? summary.total_accounts_engaged);
32
+ pushMetric(lines, 'Profile Views', metrics.profile_views ?? summary.total_views);
33
+ pushMetric(lines, 'Search Views', metrics.search_views ?? summary.total_reach);
34
+ pushMetric(lines, 'Maps Views', metrics.maps_views ?? summary.total_profile_views);
35
+ pushMetric(lines, 'Customer Actions', metrics.customer_actions ?? summary.total_accounts_engaged);
33
36
  pushMetric(lines, 'Posts', metrics.posts ?? summary.current_media_count);
34
- lines.push(`• Engagement rate (actions / profile views): ${summary.engagement_rate}%`);
35
- pushMetric(lines, 'Website clicks', metrics.website_clicks ?? summary.total_website_clicks);
36
- pushMetric(lines, 'Call clicks', metrics.call_clicks ?? summary.total_call_clicks);
37
- pushMetric(lines, 'Direction requests', metrics.direction_requests ?? summary.total_direction_requests);
38
- pushMetric(lines, 'Conversations', metrics.conversations ?? summary.total_conversations);
39
- pushMetric(lines, 'Bookings', metrics.bookings ?? summary.total_bookings);
40
37
  }
41
38
  else if (account.platform === 'pinterest') {
42
39
  pushGenericSummary(lines, summary);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posterly-mcp-server",
3
- "version": "0.19.1",
3
+ "version": "0.19.3",
4
4
  "description": "MCP server for posterly — schedule social media posts from Claude Desktop",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.poster.ly/mcp",
@@ -895,7 +895,7 @@ export class PosterlyClient {
895
895
  const SIZE_THRESHOLD = 3 * 1024 * 1024; // 3MB
896
896
 
897
897
  if (fileBuffer.length > SIZE_THRESHOLD) {
898
- // Large file: use signed URL to upload directly to Supabase Storage
898
+ // Large file: use signed URL so the API can validate actual bytes before storage.
899
899
  const signed = await this.getSignedUploadUrl(
900
900
  input.filename,
901
901
  contentType,
@@ -4,7 +4,7 @@ import type { PosterlyClient } from '../lib/api-client.js';
4
4
  export const createSignedUploadTool = {
5
5
  name: 'create_signed_upload',
6
6
  description:
7
- 'Create a signed direct-upload URL for a larger image or video. Upload the binary to upload_url, then use public_url with create_post.',
7
+ 'Create a signed upload URL for a larger image or video. Upload the binary to upload_url; the API validates actual bytes before storage, then public_url can be used with create_post.',
8
8
  inputSchema: z.object({
9
9
  filename: z.string().describe('Filename with extension, e.g. launch-video.mp4'),
10
10
  content_type: z.string().describe('MIME type, e.g. video/mp4'),
@@ -4,7 +4,7 @@ import type { AccountAnalyticsSummary, PosterlyClient } from '../lib/api-client.
4
4
  export const getAccountAnalyticsTool = {
5
5
  name: 'get_account_analytics',
6
6
  description:
7
- 'Get daily analytics snapshots and a period summary for a connected social account. Supports Instagram, Facebook, LinkedIn, Google Business Profile, Pinterest, and YouTube. Returns follower growth, reach, views, engagement rate, and platform-specific metrics.',
7
+ 'Get daily analytics snapshots and a period summary for a connected social account. Supports Instagram, Facebook, LinkedIn, Google Business Profile, Pinterest, and YouTube. For Google Business Profile, returns Profile Views, Search Views, Maps Views, Customer Actions, and Posts.',
8
8
  inputSchema: z.object({
9
9
  account_id: z
10
10
  .number()
@@ -26,8 +26,12 @@ export const getAccountAnalyticsTool = {
26
26
  const result = await client.getAccountAnalytics(input);
27
27
  const { account, range, summary, snapshots } = result;
28
28
 
29
+ const accountLabel = account.platform === 'google_business'
30
+ ? `${account.username} (Google Business, id ${account.id})`
31
+ : `@${account.username} (${account.platform}, id ${account.id})`;
32
+
29
33
  const lines: string[] = [
30
- `Analytics for @${account.username} (${account.platform}, id ${account.id})`,
34
+ `Analytics for ${accountLabel}`,
31
35
  `Range: ${range.from} → ${range.to} (${snapshots.length} daily snapshots)`,
32
36
  '',
33
37
  'Summary:',
@@ -35,17 +39,11 @@ export const getAccountAnalyticsTool = {
35
39
 
36
40
  if (account.platform === 'google_business') {
37
41
  const metrics = summary.platform_metrics || {};
38
- pushMetric(lines, 'Profile views', metrics.profile_views ?? summary.total_views);
39
- pushMetric(lines, 'Search views', metrics.search_views ?? summary.total_reach);
40
- pushMetric(lines, 'Maps views', metrics.maps_views ?? summary.total_profile_views);
41
- pushMetric(lines, 'Customer actions', metrics.customer_actions ?? summary.total_accounts_engaged);
42
+ pushMetric(lines, 'Profile Views', metrics.profile_views ?? summary.total_views);
43
+ pushMetric(lines, 'Search Views', metrics.search_views ?? summary.total_reach);
44
+ pushMetric(lines, 'Maps Views', metrics.maps_views ?? summary.total_profile_views);
45
+ pushMetric(lines, 'Customer Actions', metrics.customer_actions ?? summary.total_accounts_engaged);
42
46
  pushMetric(lines, 'Posts', metrics.posts ?? summary.current_media_count);
43
- lines.push(`• Engagement rate (actions / profile views): ${summary.engagement_rate}%`);
44
- pushMetric(lines, 'Website clicks', metrics.website_clicks ?? summary.total_website_clicks);
45
- pushMetric(lines, 'Call clicks', metrics.call_clicks ?? summary.total_call_clicks);
46
- pushMetric(lines, 'Direction requests', metrics.direction_requests ?? summary.total_direction_requests);
47
- pushMetric(lines, 'Conversations', metrics.conversations ?? summary.total_conversations);
48
- pushMetric(lines, 'Bookings', metrics.bookings ?? summary.total_bookings);
49
47
  } else if (account.platform === 'pinterest') {
50
48
  pushGenericSummary(lines, summary);
51
49
  pushMetric(lines, 'Outbound clicks', summary.total_website_clicks);