redditapis-mcp 0.10.1 → 0.10.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.2 (2026-10-14)
4
+
5
+ ### The 408 upstream_timeout read gets the same one retry
6
+
7
+ The API now answers `408 {"error":"upstream_timeout"}` when a read did not complete in
8
+ time (the body says it was not billed and names `retry_after`); before this release that
9
+ case was a 500 and the model saw it as a failed tool call. A read answered that way is
10
+ retried once after its `retry_after` (clamped 1..5 s), exactly like the 503
11
+ `upstream_unavailable` retry from 0.10.1, and a 408 that is not retried carries a hint
12
+ naming the retry. A 408 with any other error value, and a 408 on a write, are never
13
+ retried.
14
+
3
15
  ## 0.10.1 (2026-10-14)
4
16
 
5
17
  ### One bounded retry on the API's transient 503, and a clearer 429
package/README.md CHANGED
@@ -317,6 +317,8 @@ Reads need nothing but your API key -- no account linking, login, or cookie step
317
317
 
318
318
  **`HTTP 429 (rate limited)`** Wait a few seconds and retry, or reduce request frequency. For bulk work, space out calls and raise `REDDITAPIS_TIMEOUT_MS`.
319
319
 
320
+ **`HTTP 408 (upstream_timeout)`** The read did not finish in time and was not billed. The server already retried once after `retry_after`; call the tool again shortly. A `503 upstream_unavailable` on a read gets the same one retry.
321
+
320
322
  **`Request failed: timed out after 30000ms`** The default timeout is 30 seconds. For large `reddit_deep_comment_search` or paginated fetches, set `REDDITAPIS_TIMEOUT_MS` higher (for example `60000`).
321
323
 
322
324
  **Tools do not appear in Claude / Cursor** Ensure `npx` is on your PATH and Node.js 18+ is installed (`node --version`). Check your MCP client logs for startup errors.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redditapis-mcp",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "mcpName": "io.github.redditapis/redditapis-mcp",
5
5
  "description": "Official MCP server for redditapis.com. Search Reddit posts, comments, communities, users and media; read subreddits, comment trees, top posts and profiles; create and manage monitors and webhooks. Native tools for Claude, Cursor and any MCP client.",
6
6
  "repository": {
package/src/server.js CHANGED
@@ -134,6 +134,7 @@ export function hintFor(status, path) {
134
134
  for (const [re, hint] of NOT_FOUND_HINTS) if (re.test(path || "")) return hint;
135
135
  return DEFAULT_NOT_FOUND_HINT;
136
136
  }
137
+ if (status === 408) return " (the read did not complete in time; retry after the retry_after seconds)";
137
138
  if (status === 429) return " (slow down: wait the retry_after seconds, keep this key's reads in flight under the limit the message names, then retry)";
138
139
  if (status >= 500) return " (upstream API error. Retry in a moment; if persistent, contact https://www.redditapis.com)";
139
140
  return "";
@@ -279,8 +280,9 @@ export function createServer({
279
280
  // An API restart makes the gateway answer an HTML 502/503 or refuse the
280
281
  // connection for a short window. A READ is retried through it; timeouts and
281
282
  // writes never are, so a request the API may already have handled is never sent
282
- // twice (a gateway 504 is not retried for that reason). The one API JSON error
283
- // that IS retried is the read-side 503 upstream_unavailable below (0.10.1).
283
+ // twice (a gateway 504 is not retried for that reason). The API JSON errors
284
+ // that ARE retried, once, are the read-side 503 upstream_unavailable (0.10.1)
285
+ // and 408 upstream_timeout (0.10.2) below.
284
286
  // Only a REFUSED connection is retried: the request never reached the API,
285
287
  // so it cannot have been handled or billed. A reset, a broken pipe or a
286
288
  // socket dropped mid-answer can all happen after the API did the work, and
@@ -288,7 +290,9 @@ export function createServer({
288
290
  const RETRYABLE_NET = new Set(["ECONNREFUSED"]);
289
291
  const gatewayFailure = (status, text) =>
290
292
  (status === 502 || status === 503) && /^\s*<(!doctype|html)/i.test(text);
291
- // The API's own transient refusal of a READ: 503 with error upstream_unavailable.
293
+ // The API's own transient refusal of a READ: 503 with error upstream_unavailable,
294
+ // and since 0.10.2 the 408 upstream_timeout it answers when a read did not
295
+ // complete in time (the body says it was not billed and names retry_after).
292
296
  // Its body says the call was not billed and names retry_after, so ONE retry after
293
297
  // that many seconds (clamped 1..5) never double-bills and turns a per-read refusal
294
298
  // into a slow success instead of a failed tool call (0.10.1). Never a write, never
@@ -296,8 +300,10 @@ export function createServer({
296
300
  // The TOP-LEVEL error value, parsed, never a substring match (review 2026-10-14:
297
301
  // a body nesting the string elsewhere must not be retried).
298
302
  const parsedBody = (text) => { try { const v = JSON.parse(text); return v && typeof v === "object" ? v : null; } catch { return null; } };
299
- const apiTransientRead = (status, text) =>
300
- status === 503 && parsedBody(text)?.error === "upstream_unavailable";
303
+ const apiTransientRead = (status, text) => {
304
+ const err = parsedBody(text)?.error;
305
+ return (status === 503 && err === "upstream_unavailable") || (status === 408 && err === "upstream_timeout");
306
+ };
301
307
  const retryAfterMs = (text) => {
302
308
  const s = Number(parsedBody(text)?.retry_after);
303
309
  return Math.min(5, Math.max(1, Number.isFinite(s) && s > 0 ? s : 2)) * 1000;