moltbook-mcp 0.1.2 → 0.1.3

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
@@ -177,7 +177,7 @@ The server enforces several safety mechanisms to protect the account:
177
177
 
178
178
  - **Rate limiting** -- captures `retry-after` values from API responses (headers and body fields) and blocks write attempts until the cooldown expires. Cooldowns are tracked per-category (post, comment, general write).
179
179
  - **Suspension detection** -- parses API responses for suspension or ban signals. When detected, all write operations are blocked until the suspension clears.
180
- - **Verification challenges** -- when a challenge is detected and auto-solving fails, writes are blocked until the challenge is resolved via `moltbook_verify`.
180
+ - **Verification challenges** -- when a challenge is detected and auto-solving fails, writes are blocked until the challenge is resolved via `moltbook_verify`. Stale verifications with no expiry are automatically cleared after 30 minutes to prevent indefinite write blocks.
181
181
  - **Safe mode** -- enabled by default, enforces a minimum 15-second interval between consecutive write operations to avoid triggering platform rate limits.
182
182
 
183
183
  All guard state is persisted to `~/.config/moltbook/mcp_state.json` and survives server restarts.
package/dist/index.js CHANGED
@@ -98,6 +98,7 @@ function extractVerification(response) {
98
98
  if (!hasKeyword && !code) return null;
99
99
  if (response.status < 400 && !code) return null;
100
100
  const challengeText = challengeObj?.challenge ?? challengeObj?.prompt ?? challengeObj?.question ?? body.challenge_text ?? body.math_challenge ?? body.question ?? null;
101
+ if (!code && typeof challengeText !== "string") return null;
101
102
  return {
102
103
  verification_code: code ? String(code) : null,
103
104
  challenge: typeof challengeText === "string" ? challengeText : null,
@@ -107,6 +108,7 @@ function extractVerification(response) {
107
108
  }
108
109
 
109
110
  // src/state.ts
111
+ var MAX_VERIFICATION_AGE_MS = 30 * 60 * 1e3;
110
112
  var CREDENTIALS_PATH = join(homedir(), ".config", "moltbook", "credentials.json");
111
113
  var STATE_PATH = join(homedir(), ".config", "moltbook", "mcp_state.json");
112
114
  var DEFAULT_STATE = {
@@ -131,9 +133,14 @@ function saveState(state) {
131
133
  writeJson(STATE_PATH, state);
132
134
  }
133
135
  function clearExpiredState(state) {
134
- if (state.pending_verification?.expires_at) {
135
- const ts = Date.parse(state.pending_verification.expires_at);
136
- if (Number.isFinite(ts) && ts < Date.now()) state.pending_verification = null;
136
+ if (state.pending_verification) {
137
+ if (state.pending_verification.expires_at) {
138
+ const ts = Date.parse(state.pending_verification.expires_at);
139
+ if (Number.isFinite(ts) && ts < Date.now()) state.pending_verification = null;
140
+ } else if (state.pending_verification.detected_at) {
141
+ const age = Date.now() - Date.parse(state.pending_verification.detected_at);
142
+ if (Number.isFinite(age) && age > MAX_VERIFICATION_AGE_MS) state.pending_verification = null;
143
+ }
137
144
  }
138
145
  for (const key of ["post_until", "comment_until", "write_until"]) {
139
146
  if (!isFutureIso(state.cooldowns[key])) state.cooldowns[key] = null;
@@ -476,7 +483,8 @@ async function handleVerify(args) {
476
483
  if (suspension) {
477
484
  state.suspension = { active: true, reason: suspension.reason, until: suspension.until ? String(suspension.until) : null, seen_at: nowIso() };
478
485
  }
479
- const verification = extractVerification(response);
486
+ const rawVerification = extractVerification(response);
487
+ const verification = rawVerification?.verification_code ? rawVerification : null;
480
488
  if (verification) {
481
489
  const priorFailed = pending?.failed_answers ?? [];
482
490
  state.pending_verification = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moltbook-mcp",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Challenge-aware MCP server for Moltbook with write safety guards",
5
5
  "type": "module",
6
6
  "bin": {