posterly-mcp-server 0.48.3 → 0.48.4

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
@@ -123,7 +123,7 @@ Add the same server definition to your Cursor MCP settings:
123
123
 
124
124
  ## Available tools
125
125
 
126
- `posterly-mcp-server@0.48.3` exposes 62 tools covering 95 actions. The hosted HTTP endpoint exposes the same catalog minus the three signup tools: 59 tools covering 92 actions.
126
+ `posterly-mcp-server@0.48.4` exposes 62 tools covering 95 actions. The hosted HTTP endpoint exposes the same catalog minus the three signup tools: 59 tools covering 92 actions.
127
127
 
128
128
  Many tools pick what to do with one parameter: `view` (reads), `action` (writes), or `type`. A few pick their mode from which parameters you pass (for example `update_post` with `status` changes the status instead of editing). Every tool description names all of its views and actions.
129
129
 
@@ -559,12 +559,24 @@ export type SuggestedSlotBasis = 'yours' | 'platform' | 'default';
559
559
  export interface SuggestedSlot extends Slot {
560
560
  basis: SuggestedSlotBasis;
561
561
  reason: string;
562
+ /** 1-5; confidence-capped by basis (yours up to 5, platform up to 4, default up to 3). */
563
+ stars: number;
564
+ /** Tooltip text for `stars`, distinct from `reason`. */
565
+ star_reason: string;
566
+ }
567
+ export interface SuggestedTimesWeeklyRating {
568
+ stars: number;
569
+ basis: SuggestedSlotBasis;
570
+ reason: string;
571
+ estimated: boolean;
562
572
  }
563
573
  export interface SuggestedSlotsResponse {
564
574
  timezone: string;
565
575
  basis: SuggestedSlotBasis;
566
576
  basis_label: string;
567
577
  slots: SuggestedSlot[];
578
+ /** Only present when include=weekly_ratings was passed. */
579
+ weekly_ratings?: SuggestedTimesWeeklyRating[];
568
580
  }
569
581
  export interface Workspace {
570
582
  id: string;
@@ -7,6 +7,13 @@ export declare function formatLocalDateTime(value?: string | null): string;
7
7
  export declare function dashboardUrlForPost(post: Pick<Post, 'id' | 'scheduled_at'>): string;
8
8
  export declare function dashboardUrlForPosts(): string;
9
9
  export declare function dashboardUrlForPostList(posts: Array<Pick<Post, 'scheduled_at'>>): string;
10
+ /**
11
+ * Renders a 1-5 star rating as filled/empty glyphs, e.g. 4 -> "★★★★☆".
12
+ * Appends " (est.)" for a default-basis rating, matching the dashboard's
13
+ * "Estimated" badge, so a thin or absent data signal reads the same way on
14
+ * both surfaces.
15
+ */
16
+ export declare function starGlyphs(stars: unknown, estimated?: boolean): string;
10
17
  export declare function truncateText(value: string | null | undefined, max?: number): string;
11
18
  export declare function formatAccountLabel(account: Account): string;
12
19
  export declare function formatConnectedAccounts(accounts?: Account[]): string;
@@ -25,6 +25,17 @@ export function dashboardUrlForPostList(posts) {
25
25
  }
26
26
  return DASHBOARD_TABLE_URL;
27
27
  }
28
+ /**
29
+ * Renders a 1-5 star rating as filled/empty glyphs, e.g. 4 -> "★★★★☆".
30
+ * Appends " (est.)" for a default-basis rating, matching the dashboard's
31
+ * "Estimated" badge, so a thin or absent data signal reads the same way on
32
+ * both surfaces.
33
+ */
34
+ export function starGlyphs(stars, estimated = false) {
35
+ const n = Math.max(0, Math.min(5, Math.round(Number(stars)) || 0));
36
+ const glyphs = '★'.repeat(n) + '☆'.repeat(5 - n);
37
+ return estimated ? `${glyphs} (est.)` : glyphs;
38
+ }
28
39
  export function truncateText(value, max = 80) {
29
40
  const text = value?.trim() || '';
30
41
  if (!text)
@@ -1 +1 @@
1
- export declare const POSTERLY_MCP_VERSION = "0.48.3";
1
+ export declare const POSTERLY_MCP_VERSION = "0.48.4";
@@ -5,4 +5,4 @@
5
5
  // tool set (minus the intentional pre-auth signup tools that only this stdio
6
6
  // package exposes). `npm run check:mcp-parity` enforces both the version match
7
7
  // and the tool-list match, and runs in the pre-commit hook.
8
- export const POSTERLY_MCP_VERSION = '0.48.3';
8
+ export const POSTERLY_MCP_VERSION = '0.48.4';
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { formatDate, mdEmpty, mdTable, mdTitle } from '../lib/format.js';
2
+ import { formatDate, mdEmpty, mdTable, mdTitle, starGlyphs } from '../lib/format.js';
3
3
  const SUGGESTED_BASIS_LABELS = {
4
4
  yours: 'Based on your posts',
5
5
  platform: 'Popular on this platform',
@@ -7,7 +7,7 @@ const SUGGESTED_BASIS_LABELS = {
7
7
  };
8
8
  export const findSlotTool = {
9
9
  name: 'find_available_slot',
10
- description: 'Find available time slots for posting. Respects a 1-hour gap between posts and preferred hours (8am-10pm in the given timezone). Returns up to 10 slots. IMPORTANT: pass a timezone explicitly - default is America/New_York and slots will be off if the user is elsewhere. Pass workspace_id to only avoid collisions with posts in that workspace. strategy "best_engagement" (needs account_ids) ranks the next 7 days by when these accounts get the most engagement, with a reason per slot.',
10
+ description: 'Find available time slots for posting. Respects a 1-hour gap between posts and preferred hours (8am-10pm in the given timezone). Returns up to 10 slots. IMPORTANT: pass a timezone explicitly - default is America/New_York and slots will be off if the user is elsewhere. Pass workspace_id to only avoid collisions with posts in that workspace. strategy "best_engagement" (needs account_ids) ranks the next 7 days by when these accounts get the most engagement, with a 1-5 star rating and a reason per slot.',
11
11
  inputSchema: z.object({
12
12
  account_ids: z
13
13
  .array(z.string())
@@ -54,9 +54,10 @@ export const findSlotTool = {
54
54
  `Basis: ${basis}${result.timezone ? ` (${result.timezone})` : ''}`,
55
55
  // local_time already carries the date in the requested timezone, so
56
56
  // no separate Date column (a machine-local date could disagree).
57
- mdTable(['Option', 'Local time', 'Why'], slots.map((slot, index) => [
57
+ mdTable(['Option', 'Local time', 'Rating', 'Why'], slots.map((slot, index) => [
58
58
  index + 1,
59
59
  slot.local_time,
60
+ starGlyphs(slot.stars, slot.basis === 'default'),
60
61
  slot.reason || 'n/a',
61
62
  ])),
62
63
  ].join('\n\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posterly-mcp-server",
3
- "version": "0.48.3",
3
+ "version": "0.48.4",
4
4
  "mcpName": "io.github.awpthorp/posterly",
5
5
  "description": "MCP server for posterly: schedule and publish social media posts across 18 platforms from any MCP client (Claude, ChatGPT, Cursor, Windsurf, Cline, and more)",
6
6
  "license": "MIT",
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.awpthorp/posterly",
4
4
  "title": "posterly",
5
5
  "description": "Validate, schedule, publish, and analyze social content across 18 platforms with posterly.",
6
- "version": "0.48.3",
6
+ "version": "0.48.4",
7
7
  "websiteUrl": "https://www.poster.ly/mcp",
8
8
  "repository": {
9
9
  "url": "https://github.com/awpthorp/posterly",
@@ -14,7 +14,7 @@
14
14
  {
15
15
  "registryType": "npm",
16
16
  "identifier": "posterly-mcp-server",
17
- "version": "0.48.3",
17
+ "version": "0.48.4",
18
18
  "transport": {
19
19
  "type": "stdio"
20
20
  },
@@ -611,6 +611,17 @@ export type SuggestedSlotBasis = 'yours' | 'platform' | 'default';
611
611
  export interface SuggestedSlot extends Slot {
612
612
  basis: SuggestedSlotBasis;
613
613
  reason: string;
614
+ /** 1-5; confidence-capped by basis (yours up to 5, platform up to 4, default up to 3). */
615
+ stars: number;
616
+ /** Tooltip text for `stars`, distinct from `reason`. */
617
+ star_reason: string;
618
+ }
619
+
620
+ export interface SuggestedTimesWeeklyRating {
621
+ stars: number;
622
+ basis: SuggestedSlotBasis;
623
+ reason: string;
624
+ estimated: boolean;
614
625
  }
615
626
 
616
627
  export interface SuggestedSlotsResponse {
@@ -618,6 +629,8 @@ export interface SuggestedSlotsResponse {
618
629
  basis: SuggestedSlotBasis;
619
630
  basis_label: string;
620
631
  slots: SuggestedSlot[];
632
+ /** Only present when include=weekly_ratings was passed. */
633
+ weekly_ratings?: SuggestedTimesWeeklyRating[];
621
634
  }
622
635
 
623
636
  export interface Workspace {
package/src/lib/format.ts CHANGED
@@ -33,6 +33,18 @@ export function dashboardUrlForPostList(posts: Array<Pick<Post, 'scheduled_at'>>
33
33
  return DASHBOARD_TABLE_URL;
34
34
  }
35
35
 
36
+ /**
37
+ * Renders a 1-5 star rating as filled/empty glyphs, e.g. 4 -> "★★★★☆".
38
+ * Appends " (est.)" for a default-basis rating, matching the dashboard's
39
+ * "Estimated" badge, so a thin or absent data signal reads the same way on
40
+ * both surfaces.
41
+ */
42
+ export function starGlyphs(stars: unknown, estimated = false): string {
43
+ const n = Math.max(0, Math.min(5, Math.round(Number(stars)) || 0));
44
+ const glyphs = '★'.repeat(n) + '☆'.repeat(5 - n);
45
+ return estimated ? `${glyphs} (est.)` : glyphs;
46
+ }
47
+
36
48
  export function truncateText(value: string | null | undefined, max = 80): string {
37
49
  const text = value?.trim() || '';
38
50
  if (!text) return '(empty)';
@@ -5,4 +5,4 @@
5
5
  // tool set (minus the intentional pre-auth signup tools that only this stdio
6
6
  // package exposes). `npm run check:mcp-parity` enforces both the version match
7
7
  // and the tool-list match, and runs in the pre-commit hook.
8
- export const POSTERLY_MCP_VERSION = '0.48.3';
8
+ export const POSTERLY_MCP_VERSION = '0.48.4';
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import type { PosterlyClient } from '../lib/api-client.js';
3
- import { formatDate, mdEmpty, mdTable, mdTitle } from '../lib/format.js';
3
+ import { formatDate, mdEmpty, mdTable, mdTitle, starGlyphs } from '../lib/format.js';
4
4
 
5
5
  const SUGGESTED_BASIS_LABELS: Record<string, string> = {
6
6
  yours: 'Based on your posts',
@@ -11,7 +11,7 @@ const SUGGESTED_BASIS_LABELS: Record<string, string> = {
11
11
  export const findSlotTool = {
12
12
  name: 'find_available_slot',
13
13
  description:
14
- 'Find available time slots for posting. Respects a 1-hour gap between posts and preferred hours (8am-10pm in the given timezone). Returns up to 10 slots. IMPORTANT: pass a timezone explicitly - default is America/New_York and slots will be off if the user is elsewhere. Pass workspace_id to only avoid collisions with posts in that workspace. strategy "best_engagement" (needs account_ids) ranks the next 7 days by when these accounts get the most engagement, with a reason per slot.',
14
+ 'Find available time slots for posting. Respects a 1-hour gap between posts and preferred hours (8am-10pm in the given timezone). Returns up to 10 slots. IMPORTANT: pass a timezone explicitly - default is America/New_York and slots will be off if the user is elsewhere. Pass workspace_id to only avoid collisions with posts in that workspace. strategy "best_engagement" (needs account_ids) ranks the next 7 days by when these accounts get the most engagement, with a 1-5 star rating and a reason per slot.',
15
15
  inputSchema: z.object({
16
16
  account_ids: z
17
17
  .array(z.string())
@@ -69,10 +69,11 @@ export const findSlotTool = {
69
69
  // local_time already carries the date in the requested timezone, so
70
70
  // no separate Date column (a machine-local date could disagree).
71
71
  mdTable(
72
- ['Option', 'Local time', 'Why'],
72
+ ['Option', 'Local time', 'Rating', 'Why'],
73
73
  slots.map((slot, index) => [
74
74
  index + 1,
75
75
  slot.local_time,
76
+ starGlyphs(slot.stars, slot.basis === 'default'),
76
77
  slot.reason || 'n/a',
77
78
  ]),
78
79
  ),