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 +12 -0
- package/README.md +2 -0
- package/package.json +1 -1
- package/src/server.js +11 -5
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.
|
|
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
|
|
283
|
-
// that
|
|
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
|
-
|
|
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;
|