@buzzposter/mcp 0.1.6 → 0.1.8

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/dist/index.js CHANGED
@@ -262,6 +262,9 @@ var BuzzPosterClient = class {
262
262
  async getDefaultAudience() {
263
263
  return this.request("GET", "/api/v1/audiences/default");
264
264
  }
265
+ async createAudience(data) {
266
+ return this.request("POST", "/api/v1/audiences", data);
267
+ }
265
268
  async updateAudience(id, data) {
266
269
  return this.request("PUT", `/api/v1/audiences/${id}`, data);
267
270
  }
@@ -694,7 +697,9 @@ Call this tool again with confirmed=true to schedule.`;
694
697
  async (args) => {
695
698
  const body = {
696
699
  content: args.content,
697
- platforms: args.platforms.map((p) => ({ platform: p }))
700
+ platforms: args.platforms.map((p) => ({ platform: p })),
701
+ publishNow: false,
702
+ status: "draft"
698
703
  };
699
704
  if (args.media_urls?.length) {
700
705
  body.mediaItems = args.media_urls.map((url) => ({
@@ -703,6 +708,15 @@ Call this tool again with confirmed=true to schedule.`;
703
708
  }));
704
709
  }
705
710
  const result = await client2.createPost(body);
711
+ if (result?.status && result.status !== "draft") {
712
+ return {
713
+ content: [{
714
+ type: "text",
715
+ text: `ERROR: Post was saved with status "${result.status}" instead of "draft". Post ID: ${result.id ?? "unknown"}. Check the Late dashboard immediately.`
716
+ }],
717
+ isError: true
718
+ };
719
+ }
706
720
  return {
707
721
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
708
722
  };
@@ -2134,16 +2148,17 @@ function registerAudienceTools(server2, client2) {
2134
2148
  );
2135
2149
  server2.tool(
2136
2150
  "update_audience",
2137
- `Update an existing audience profile. Only the fields you provide will be changed; omitted fields are left as-is.
2151
+ `Create or update a target audience profile. This is an upsert \u2014 if no audience_id is provided it will try to update the default audience, or create a new one if none exists. Only the fields you provide will be changed; omitted fields are left as-is.
2138
2152
 
2139
2153
  USAGE GUIDELINES:
2140
2154
  - Call get_audience first to see the current state before making changes
2141
2155
  - Always set confirmed=false first to preview the changes, then confirmed=true after user approval
2142
2156
  - When updating array fields (pain_points, motivations, preferred_platforms), include the FULL array (existing + new items), not just the new ones
2157
+ - Omit audience_id to update the default audience or create a new one if none exists
2143
2158
  - Max limits: name 100 chars, description 500 chars`,
2144
2159
  {
2145
- audience_id: z9.string().describe("The audience ID to update (required)"),
2146
- name: z9.string().max(100).optional().describe("Audience profile name (e.g. 'SaaS Founders', 'Health-Conscious Millennials')"),
2160
+ audience_id: z9.string().optional().describe("Audience ID to update. Omit to update the default audience, or create one if none exists."),
2161
+ name: z9.string().max(100).optional().describe("Audience profile name (e.g. 'SaaS Founders', 'Health-Conscious Millennials'). Required when creating a new audience."),
2147
2162
  description: z9.string().max(500).optional().describe("Brief description of who this audience is"),
2148
2163
  demographics: z9.string().optional().describe("Demographic details \u2014 age range, location, income level, education, etc."),
2149
2164
  pain_points: z9.array(z9.string()).optional().describe("Problems and frustrations the audience faces. Send the FULL list, not just additions."),
@@ -2185,10 +2200,33 @@ USAGE GUIDELINES:
2185
2200
  isError: true
2186
2201
  };
2187
2202
  }
2203
+ let targetId = args.audience_id;
2204
+ let isCreating = false;
2205
+ if (!targetId) {
2206
+ try {
2207
+ const defaultAudience = await client2.getDefaultAudience();
2208
+ targetId = String(defaultAudience.id);
2209
+ } catch {
2210
+ isCreating = true;
2211
+ }
2212
+ }
2213
+ if (isCreating && !payload.name) {
2214
+ return {
2215
+ content: [
2216
+ {
2217
+ type: "text",
2218
+ text: "No audience exists yet. Provide a **name** to create one (e.g. name: 'SaaS Founders')."
2219
+ }
2220
+ ],
2221
+ isError: true
2222
+ };
2223
+ }
2188
2224
  if (args.confirmed !== true) {
2189
2225
  const lines2 = [];
2190
- lines2.push("## Audience Update Preview");
2191
- lines2.push(`**Audience ID:** ${args.audience_id}`);
2226
+ lines2.push(isCreating ? "## New Audience Preview" : "## Audience Update Preview");
2227
+ if (!isCreating) {
2228
+ lines2.push(`**Audience ID:** ${targetId}`);
2229
+ }
2192
2230
  lines2.push("");
2193
2231
  if (payload.name) {
2194
2232
  lines2.push(`**Name:** ${payload.name}`);
@@ -2246,9 +2284,15 @@ USAGE GUIDELINES:
2246
2284
  content: [{ type: "text", text: lines2.join("\n") }]
2247
2285
  };
2248
2286
  }
2249
- const result = await client2.updateAudience(args.audience_id, payload);
2287
+ let result;
2288
+ if (isCreating) {
2289
+ if (payload.isDefault === void 0) payload.isDefault = true;
2290
+ result = await client2.createAudience(payload);
2291
+ } else {
2292
+ result = await client2.updateAudience(targetId, payload);
2293
+ }
2250
2294
  const lines = [];
2251
- lines.push(`Audience "${result.name}" has been updated successfully.`);
2295
+ lines.push(`Audience "${result.name}" has been ${isCreating ? "created" : "updated"} successfully.`);
2252
2296
  lines.push("");
2253
2297
  const summary = [];
2254
2298
  if (payload.name) summary.push("name");
@@ -2260,7 +2304,7 @@ USAGE GUIDELINES:
2260
2304
  if (payload.toneNotes) summary.push("tone notes");
2261
2305
  if (payload.contentPreferences) summary.push("content preferences");
2262
2306
  if (payload.isDefault !== void 0) summary.push("default status");
2263
- lines.push(`**Updated:** ${summary.join(", ")}`);
2307
+ lines.push(`**${isCreating ? "Created with" : "Updated"}:** ${summary.join(", ")}`);
2264
2308
  return {
2265
2309
  content: [{ type: "text", text: lines.join("\n") }]
2266
2310
  };
package/dist/tools.d.ts CHANGED
@@ -76,6 +76,7 @@ declare class BuzzPosterClient {
76
76
  updateBrandVoice(data: Record<string, unknown>): Promise<unknown>;
77
77
  getAudience(id: string): Promise<unknown>;
78
78
  getDefaultAudience(): Promise<unknown>;
79
+ createAudience(data: Record<string, unknown>): Promise<unknown>;
79
80
  updateAudience(id: string, data: Record<string, unknown>): Promise<unknown>;
80
81
  getTemplate(id?: string): Promise<unknown>;
81
82
  listTemplates(): Promise<unknown>;
package/dist/tools.js CHANGED
@@ -256,6 +256,9 @@ var BuzzPosterClient = class {
256
256
  async getDefaultAudience() {
257
257
  return this.request("GET", "/api/v1/audiences/default");
258
258
  }
259
+ async createAudience(data) {
260
+ return this.request("POST", "/api/v1/audiences", data);
261
+ }
259
262
  async updateAudience(id, data) {
260
263
  return this.request("PUT", `/api/v1/audiences/${id}`, data);
261
264
  }
@@ -688,7 +691,9 @@ Call this tool again with confirmed=true to schedule.`;
688
691
  async (args) => {
689
692
  const body = {
690
693
  content: args.content,
691
- platforms: args.platforms.map((p) => ({ platform: p }))
694
+ platforms: args.platforms.map((p) => ({ platform: p })),
695
+ publishNow: false,
696
+ status: "draft"
692
697
  };
693
698
  if (args.media_urls?.length) {
694
699
  body.mediaItems = args.media_urls.map((url) => ({
@@ -697,6 +702,15 @@ Call this tool again with confirmed=true to schedule.`;
697
702
  }));
698
703
  }
699
704
  const result = await client.createPost(body);
705
+ if (result?.status && result.status !== "draft") {
706
+ return {
707
+ content: [{
708
+ type: "text",
709
+ text: `ERROR: Post was saved with status "${result.status}" instead of "draft". Post ID: ${result.id ?? "unknown"}. Check the Late dashboard immediately.`
710
+ }],
711
+ isError: true
712
+ };
713
+ }
700
714
  return {
701
715
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
702
716
  };
@@ -2864,16 +2878,17 @@ function registerAudienceTools(server, client) {
2864
2878
  );
2865
2879
  server.tool(
2866
2880
  "update_audience",
2867
- `Update an existing audience profile. Only the fields you provide will be changed; omitted fields are left as-is.
2881
+ `Create or update a target audience profile. This is an upsert \u2014 if no audience_id is provided it will try to update the default audience, or create a new one if none exists. Only the fields you provide will be changed; omitted fields are left as-is.
2868
2882
 
2869
2883
  USAGE GUIDELINES:
2870
2884
  - Call get_audience first to see the current state before making changes
2871
2885
  - Always set confirmed=false first to preview the changes, then confirmed=true after user approval
2872
2886
  - When updating array fields (pain_points, motivations, preferred_platforms), include the FULL array (existing + new items), not just the new ones
2887
+ - Omit audience_id to update the default audience or create a new one if none exists
2873
2888
  - Max limits: name 100 chars, description 500 chars`,
2874
2889
  {
2875
- audience_id: z10.string().describe("The audience ID to update (required)"),
2876
- name: z10.string().max(100).optional().describe("Audience profile name (e.g. 'SaaS Founders', 'Health-Conscious Millennials')"),
2890
+ audience_id: z10.string().optional().describe("Audience ID to update. Omit to update the default audience, or create one if none exists."),
2891
+ name: z10.string().max(100).optional().describe("Audience profile name (e.g. 'SaaS Founders', 'Health-Conscious Millennials'). Required when creating a new audience."),
2877
2892
  description: z10.string().max(500).optional().describe("Brief description of who this audience is"),
2878
2893
  demographics: z10.string().optional().describe("Demographic details \u2014 age range, location, income level, education, etc."),
2879
2894
  pain_points: z10.array(z10.string()).optional().describe("Problems and frustrations the audience faces. Send the FULL list, not just additions."),
@@ -2915,10 +2930,33 @@ USAGE GUIDELINES:
2915
2930
  isError: true
2916
2931
  };
2917
2932
  }
2933
+ let targetId = args.audience_id;
2934
+ let isCreating = false;
2935
+ if (!targetId) {
2936
+ try {
2937
+ const defaultAudience = await client.getDefaultAudience();
2938
+ targetId = String(defaultAudience.id);
2939
+ } catch {
2940
+ isCreating = true;
2941
+ }
2942
+ }
2943
+ if (isCreating && !payload.name) {
2944
+ return {
2945
+ content: [
2946
+ {
2947
+ type: "text",
2948
+ text: "No audience exists yet. Provide a **name** to create one (e.g. name: 'SaaS Founders')."
2949
+ }
2950
+ ],
2951
+ isError: true
2952
+ };
2953
+ }
2918
2954
  if (args.confirmed !== true) {
2919
2955
  const lines2 = [];
2920
- lines2.push("## Audience Update Preview");
2921
- lines2.push(`**Audience ID:** ${args.audience_id}`);
2956
+ lines2.push(isCreating ? "## New Audience Preview" : "## Audience Update Preview");
2957
+ if (!isCreating) {
2958
+ lines2.push(`**Audience ID:** ${targetId}`);
2959
+ }
2922
2960
  lines2.push("");
2923
2961
  if (payload.name) {
2924
2962
  lines2.push(`**Name:** ${payload.name}`);
@@ -2976,9 +3014,15 @@ USAGE GUIDELINES:
2976
3014
  content: [{ type: "text", text: lines2.join("\n") }]
2977
3015
  };
2978
3016
  }
2979
- const result = await client.updateAudience(args.audience_id, payload);
3017
+ let result;
3018
+ if (isCreating) {
3019
+ if (payload.isDefault === void 0) payload.isDefault = true;
3020
+ result = await client.createAudience(payload);
3021
+ } else {
3022
+ result = await client.updateAudience(targetId, payload);
3023
+ }
2980
3024
  const lines = [];
2981
- lines.push(`Audience "${result.name}" has been updated successfully.`);
3025
+ lines.push(`Audience "${result.name}" has been ${isCreating ? "created" : "updated"} successfully.`);
2982
3026
  lines.push("");
2983
3027
  const summary = [];
2984
3028
  if (payload.name) summary.push("name");
@@ -2990,7 +3034,7 @@ USAGE GUIDELINES:
2990
3034
  if (payload.toneNotes) summary.push("tone notes");
2991
3035
  if (payload.contentPreferences) summary.push("content preferences");
2992
3036
  if (payload.isDefault !== void 0) summary.push("default status");
2993
- lines.push(`**Updated:** ${summary.join(", ")}`);
3037
+ lines.push(`**${isCreating ? "Created with" : "Updated"}:** ${summary.join(", ")}`);
2994
3038
  return {
2995
3039
  content: [{ type: "text", text: lines.join("\n") }]
2996
3040
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buzzposter/mcp",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "BuzzPoster MCP server - Social media, newsletters, and media hosting for Claude Desktop",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",