mcp-scraper 0.28.1 → 0.28.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/README.md CHANGED
@@ -88,7 +88,7 @@ Build the branded one-click bundle:
88
88
  npm run build:mcpb
89
89
  ```
90
90
 
91
- The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.26.3`, SHA-256 `3d2725b44772eb50c0514f9b89a00fa69d3bbcd57644d29cefc355feeefbd595`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, and API-key configuration field from the bundle manifest.
91
+ The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.28.2`, SHA-256 `f44ab0f1ce8ef9680558b6f3e7e21cf45d1621a826f1b803180512c7baa9a4fb`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, and API-key configuration field from the bundle manifest.
92
92
 
93
93
  The MCPB install exposes every tool — web-intelligence plus all `browser_*` tools — through the one `mcp-scraper` server.
94
94
 
@@ -29723,7 +29723,7 @@ var PACKAGE_VERSION;
29723
29723
  var init_version = __esm({
29724
29724
  "src/version.ts"() {
29725
29725
  "use strict";
29726
- PACKAGE_VERSION = "0.28.0";
29726
+ PACKAGE_VERSION = "0.28.2";
29727
29727
  }
29728
29728
  });
29729
29729
 
@@ -41217,33 +41217,67 @@ function workspaceRecord(vault, note) {
41217
41217
  };
41218
41218
  }
41219
41219
  function defaultType(vault) {
41220
- if (vault === "People") return "person";
41220
+ if (vault === "People" || vault === "Communications") return "unclassified";
41221
41221
  if (vault === "Projects") return "project";
41222
41222
  if (vault === "Tasks") return "task";
41223
- return "activity";
41223
+ return "unclassified";
41224
41224
  }
41225
41225
  function defaultStatus(vault) {
41226
41226
  if (vault === "People") return "active";
41227
41227
  if (vault === "Projects") return "active";
41228
41228
  if (vault === "Tasks") return "to_do";
41229
- return "triaged";
41229
+ return "inbox";
41230
+ }
41231
+ function shouldRetryMemoryRead(error) {
41232
+ return /deadlock|timeout|timed out|temporar|econnreset|fetch failed/i.test(error ?? "");
41233
+ }
41234
+ function sleep(ms) {
41235
+ return new Promise((resolve) => setTimeout(resolve, ms));
41236
+ }
41237
+ async function readMemory(tool, args, token) {
41238
+ let result = await memoryCall(tool, args, token);
41239
+ for (let attempt = 1; !result.ok && attempt < MAX_MEMORY_READ_ATTEMPTS && shouldRetryMemoryRead(result.error); attempt += 1) {
41240
+ await sleep(attempt * 150);
41241
+ result = await memoryCall(tool, args, token);
41242
+ }
41243
+ return result;
41244
+ }
41245
+ async function mapWithConcurrency(items, limit, map) {
41246
+ const values = new Array(items.length);
41247
+ let cursor = 0;
41248
+ const worker = async () => {
41249
+ while (cursor < items.length) {
41250
+ const index = cursor;
41251
+ cursor += 1;
41252
+ values[index] = await map(items[index]);
41253
+ }
41254
+ };
41255
+ await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()));
41256
+ return values;
41230
41257
  }
41231
41258
  async function readVault(vault, token) {
41232
- const list = await memoryCall("listTool", { vault }, token);
41259
+ const list = await readMemory("listTool", { vault }, token);
41233
41260
  if (!list.ok) throw new Error(list.error ?? `unable to read ${vault}`);
41234
- const noteRefs = (list.notes ?? []).slice(0, 200);
41235
- const notes = await Promise.all(
41236
- noteRefs.map(async ({ path: path6 }) => memoryCall("getTool", { vault, path: path6 }, token))
41261
+ const noteRefs = (list.notes ?? []).slice(0, MAX_VAULT_RECORDS);
41262
+ const notes = await mapWithConcurrency(
41263
+ noteRefs,
41264
+ MAX_MEMORY_READ_CONCURRENCY,
41265
+ ({ path: path6 }) => readMemory("getTool", { vault, path: path6 }, token)
41237
41266
  );
41267
+ const failed = notes.find((result) => !result.ok);
41268
+ if (failed && !failed.ok) throw new Error(failed.error ?? `unable to read ${vault} record`);
41238
41269
  return notes.filter((result) => result.ok && !!result.note).map((result) => workspaceRecord(vault, result.note));
41239
41270
  }
41240
- var import_hono22, VAULTS, vaultApp;
41271
+ var import_hono22, VAULTS, MAX_VAULT_RECORDS, MAX_MEMORY_READ_CONCURRENCY, MAX_MEMORY_READ_ATTEMPTS, vaultApp;
41241
41272
  var init_vault_routes = __esm({
41242
41273
  "src/api/vault-routes.ts"() {
41243
41274
  "use strict";
41244
41275
  import_hono22 = require("hono");
41245
41276
  init_memory();
41246
41277
  VAULTS = ["People", "Projects", "Tasks", "Communications"];
41278
+ MAX_VAULT_RECORDS = 200;
41279
+ MAX_MEMORY_READ_CONCURRENCY = 4;
41280
+ MAX_MEMORY_READ_ATTEMPTS = 3;
41247
41281
  vaultApp = new import_hono22.Hono();
41248
41282
  vaultApp.use("/api/*", async (c, next) => {
41249
41283
  cors(c);
@@ -41256,7 +41290,8 @@ var init_vault_routes = __esm({
41256
41290
  try {
41257
41291
  const requested = c.req.query("vault");
41258
41292
  const vaults = isVault(requested) ? [requested] : VAULTS;
41259
- const results = await Promise.all(vaults.map((vault) => readVault(vault, token)));
41293
+ const results = [];
41294
+ for (const vault of vaults) results.push(await readVault(vault, token));
41260
41295
  const records = results.flat().sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
41261
41296
  return c.json({ ok: true, records, limited: results.some((result) => result.length >= 200) });
41262
41297
  } catch (error) {
@@ -41286,7 +41321,7 @@ var init_vault_routes = __esm({
41286
41321
  const status = stringValue(body.status, 80);
41287
41322
  const baseRevision = typeof body.baseRevision === "number" && Number.isInteger(body.baseRevision) ? body.baseRevision : void 0;
41288
41323
  if (!isVault(vault) || !path6 || !status) return c.json({ ok: false, error: "valid vault, path, and status are required" }, 400);
41289
- const current = await memoryCall("getTool", { vault, path: path6 }, token);
41324
+ const current = await readMemory("getTool", { vault, path: path6 }, token);
41290
41325
  if (!current.ok || !current.note) return c.json(current, current.ok ? 404 : 502);
41291
41326
  const result = await memoryCall("putTool", {
41292
41327
  vault,
@@ -41298,6 +41333,67 @@ var init_vault_routes = __esm({
41298
41333
  }, token);
41299
41334
  return c.json(result, result.ok ? 200 : result.conflict ? 409 : 502);
41300
41335
  });
41336
+ vaultApp.post("/api/records/update", async (c) => {
41337
+ const body = await c.req.json().catch(() => ({}));
41338
+ const token = typeof body.token === "string" ? body.token : void 0;
41339
+ if (!validToken(token)) return c.json({ ok: false, error: "missing or malformed Vault App link" }, 401);
41340
+ const vault = body.vault;
41341
+ const path6 = stringValue(body.path, 320);
41342
+ const title = typeof body.title === "string" ? stringValue(body.title, 320) : void 0;
41343
+ const content = typeof body.content === "string" && body.content.length <= 1e5 ? body.content : void 0;
41344
+ const props = body.props === void 0 ? void 0 : propsValue(body.props);
41345
+ const baseRevision = typeof body.baseRevision === "number" && Number.isInteger(body.baseRevision) ? body.baseRevision : void 0;
41346
+ if (!isVault(vault) || !path6 || body.title !== void 0 && !title || body.props !== void 0 && !props) {
41347
+ return c.json({ ok: false, error: "valid vault, path, and optional record fields are required" }, 400);
41348
+ }
41349
+ const current = await readMemory("getTool", { vault, path: path6 }, token);
41350
+ if (!current.ok || !current.note) return c.json(current, current.ok ? 404 : 502);
41351
+ const result = await memoryCall("putTool", {
41352
+ vault,
41353
+ path: path6,
41354
+ title: title ?? current.note.title,
41355
+ content: content ?? current.note.content,
41356
+ props: { ...current.note.props ?? {}, ...props ?? {} },
41357
+ baseRevision: baseRevision ?? current.note.revision
41358
+ }, token);
41359
+ return c.json(result, result.ok ? 200 : result.conflict ? 409 : 502);
41360
+ });
41361
+ vaultApp.post("/api/communications/review", async (c) => {
41362
+ const body = await c.req.json().catch(() => ({}));
41363
+ const token = typeof body.token === "string" ? body.token : void 0;
41364
+ if (!validToken(token)) return c.json({ ok: false, error: "missing or malformed Vault App link" }, 401);
41365
+ const path6 = stringValue(body.path, 320);
41366
+ const action = stringValue(body.action, 24);
41367
+ const title = typeof body.title === "string" ? stringValue(body.title, 320) : void 0;
41368
+ const content = typeof body.content === "string" && body.content.length <= 1e5 ? body.content : void 0;
41369
+ const feedback = typeof body.feedback === "string" ? body.feedback.trim().slice(0, 1e4) : void 0;
41370
+ const baseRevision = typeof body.baseRevision === "number" && Number.isInteger(body.baseRevision) ? body.baseRevision : void 0;
41371
+ if (!path6 || !action || !["accept", "deny", "edit"].includes(action) || body.title !== void 0 && !title) {
41372
+ return c.json({ ok: false, error: "valid path, action, and optional draft fields are required" }, 400);
41373
+ }
41374
+ const current = await readMemory("getTool", { vault: "Communications", path: path6 }, token);
41375
+ if (!current.ok || !current.note) return c.json(current, current.ok ? 404 : 502);
41376
+ if (current.note.props?.type !== "email") return c.json({ ok: false, error: "only email communications can be reviewed" }, 400);
41377
+ const reviewed = action === "accept" || action === "deny";
41378
+ const reviewState = action === "accept" ? "accepted" : action === "deny" ? "denied" : "pending";
41379
+ const status = action === "accept" ? "triaged" : action === "deny" ? "archived" : typeof current.note.props?.status === "string" ? current.note.props.status : "inbox";
41380
+ const props = {
41381
+ ...current.note.props ?? {},
41382
+ status,
41383
+ review_state: reviewState,
41384
+ ...reviewed ? { reviewed_at: (/* @__PURE__ */ new Date()).toISOString() } : {},
41385
+ ...feedback ? { review_feedback: feedback } : {}
41386
+ };
41387
+ const result = await memoryCall("putTool", {
41388
+ vault: "Communications",
41389
+ path: path6,
41390
+ title: title ?? current.note.title,
41391
+ content: content ?? current.note.content,
41392
+ props,
41393
+ baseRevision: baseRevision ?? current.note.revision
41394
+ }, token);
41395
+ return c.json(result, result.ok ? 200 : result.conflict ? 409 : 502);
41396
+ });
41301
41397
  vaultApp.post("/api/activity", async (c) => {
41302
41398
  const body = await c.req.json().catch(() => ({}));
41303
41399
  const token = typeof body.token === "string" ? body.token : void 0;