posterly-mcp-server 0.20.0 → 0.20.1

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
@@ -108,7 +108,7 @@ Add the same server definition to your Cursor MCP settings:
108
108
 
109
109
  ## Available tools
110
110
 
111
- `posterly-mcp-server@0.20.0` exposes 56 tools.
111
+ `posterly-mcp-server@0.20.1` exposes 56 tools.
112
112
 
113
113
  Public setup tools work before `POSTERLY_API_KEY` exists:
114
114
 
@@ -85,7 +85,7 @@ export class PosterlyClient {
85
85
  const res = await fetch(url, init);
86
86
  if (!res.ok) {
87
87
  const err = await res.json().catch(() => ({ error: res.statusText }));
88
- throw new Error(err.error || `API error: ${res.status}`);
88
+ throw new Error(formatApiError(res, err));
89
89
  }
90
90
  return res.json();
91
91
  }
@@ -100,7 +100,7 @@ export class PosterlyClient {
100
100
  const res = await fetch(url, init);
101
101
  if (!res.ok) {
102
102
  const err = await res.json().catch(() => ({ error: res.statusText }));
103
- throw new Error(err.error || `API error: ${res.status}`);
103
+ throw new Error(formatApiError(res, err));
104
104
  }
105
105
  return res.json();
106
106
  }
@@ -470,6 +470,24 @@ function formatProbeError(data, fallback, statusText) {
470
470
  }
471
471
  return fallback || statusText || 'API request failed';
472
472
  }
473
+ function formatApiError(res, data) {
474
+ const message = data?.error || data?.message || `API error: ${res.status}`;
475
+ if (res.status !== 429) {
476
+ return message;
477
+ }
478
+ const retryAfter = data?.retry_after || res.headers.get('retry-after');
479
+ const requestId = data?.request_id || res.headers.get('x-request-id');
480
+ const limit = data?.limit || res.headers.get('x-ratelimit-limit');
481
+ const reset = data?.reset || res.headers.get('x-ratelimit-reset');
482
+ return [
483
+ 'Rate limit reached.',
484
+ retryAfter ? `Try again in ${retryAfter} seconds.` : '',
485
+ limit ? `Limit: ${limit}.` : '',
486
+ reset ? `Reset: ${reset}.` : '',
487
+ requestId ? `Request ID: ${requestId}.` : '',
488
+ message && message !== 'Rate limit exceeded' ? `Details: ${message}` : '',
489
+ ].filter(Boolean).join(' ');
490
+ }
473
491
  function guessContentType(filename) {
474
492
  const ext = filename.split('.').pop()?.toLowerCase();
475
493
  const map = {
@@ -1 +1 @@
1
- export declare const POSTERLY_MCP_VERSION = "0.20.0";
1
+ export declare const POSTERLY_MCP_VERSION = "0.20.1";
@@ -1 +1 @@
1
- export const POSTERLY_MCP_VERSION = '0.20.0';
1
+ export const POSTERLY_MCP_VERSION = '0.20.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posterly-mcp-server",
3
- "version": "0.20.0",
3
+ "version": "0.20.1",
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",
@@ -611,7 +611,7 @@ export class PosterlyClient {
611
611
 
612
612
  if (!res.ok) {
613
613
  const err = await res.json().catch(() => ({ error: res.statusText }));
614
- throw new Error(err.error || `API error: ${res.status}`);
614
+ throw new Error(formatApiError(res, err));
615
615
  }
616
616
 
617
617
  return res.json() as Promise<T>;
@@ -635,7 +635,7 @@ export class PosterlyClient {
635
635
 
636
636
  if (!res.ok) {
637
637
  const err = await res.json().catch(() => ({ error: res.statusText }));
638
- throw new Error(err.error || `API error: ${res.status}`);
638
+ throw new Error(formatApiError(res, err));
639
639
  }
640
640
 
641
641
  return res.json() as Promise<T>;
@@ -1222,6 +1222,27 @@ function formatProbeError(data: any, fallback: string, statusText: string): stri
1222
1222
  return fallback || statusText || 'API request failed';
1223
1223
  }
1224
1224
 
1225
+ function formatApiError(res: Response, data: any): string {
1226
+ const message = data?.error || data?.message || `API error: ${res.status}`;
1227
+ if (res.status !== 429) {
1228
+ return message;
1229
+ }
1230
+
1231
+ const retryAfter = data?.retry_after || res.headers.get('retry-after');
1232
+ const requestId = data?.request_id || res.headers.get('x-request-id');
1233
+ const limit = data?.limit || res.headers.get('x-ratelimit-limit');
1234
+ const reset = data?.reset || res.headers.get('x-ratelimit-reset');
1235
+
1236
+ return [
1237
+ 'Rate limit reached.',
1238
+ retryAfter ? `Try again in ${retryAfter} seconds.` : '',
1239
+ limit ? `Limit: ${limit}.` : '',
1240
+ reset ? `Reset: ${reset}.` : '',
1241
+ requestId ? `Request ID: ${requestId}.` : '',
1242
+ message && message !== 'Rate limit exceeded' ? `Details: ${message}` : '',
1243
+ ].filter(Boolean).join(' ');
1244
+ }
1245
+
1225
1246
  function guessContentType(filename: string): string {
1226
1247
  const ext = filename.split('.').pop()?.toLowerCase();
1227
1248
  const map: Record<string, string> = {
@@ -1 +1 @@
1
- export const POSTERLY_MCP_VERSION = '0.20.0';
1
+ export const POSTERLY_MCP_VERSION = '0.20.1';