signupgenius-mcp 1.0.7 → 1.1.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/auth.js +6 -0
- package/dist/bundle.js +317 -17
- package/dist/index.js +1 -1
- package/package.json +3 -2
- package/server.json +2 -2
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"metadata": {
|
|
9
9
|
"description": "MCP server for SignUpGenius — read sign-ups, slot reports, and groups; add group members.",
|
|
10
|
-
"version": "1.
|
|
10
|
+
"version": "1.1.1"
|
|
11
11
|
},
|
|
12
12
|
"plugins": [
|
|
13
13
|
{
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"displayName": "SignUpGenius",
|
|
16
16
|
"source": "./",
|
|
17
17
|
"description": "SignUpGenius MCP server for Claude — sign-ups, slot reports, and groups via natural language. Free or Pro accounts.",
|
|
18
|
-
"version": "1.
|
|
18
|
+
"version": "1.1.1",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Chris Hall"
|
|
21
21
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "signupgenius-mcp",
|
|
3
3
|
"displayName": "SignUpGenius",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"description": "SignUpGenius MCP server for Claude — read sign-ups, slot reports, and groups; add group members. Three auth paths: Pro API key, email/password, or sign in via the fetchproxy browser extension.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Chris Hall",
|
package/dist/auth.js
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
// - `loadAccount()` (the existing env-var resolver) is reused as-is so the
|
|
47
47
|
// legacy paths keep working unchanged.
|
|
48
48
|
import { bootstrap } from '@fetchproxy/bootstrap';
|
|
49
|
+
import { classifyBridgeError } from '@fetchproxy/server';
|
|
49
50
|
import { loadAccount } from './config.js';
|
|
50
51
|
import pkg from '../package.json' with { type: 'json' };
|
|
51
52
|
function readEnv(key) {
|
|
@@ -150,6 +151,11 @@ export async function resolveAuth() {
|
|
|
150
151
|
};
|
|
151
152
|
}
|
|
152
153
|
catch (e) {
|
|
154
|
+
// Typed 0.8.0 error: SW retry already exhausted — surface `.hint` verbatim.
|
|
155
|
+
if (classifyBridgeError(e) === 'bridge_down') {
|
|
156
|
+
const downErr = e;
|
|
157
|
+
throw new Error(`SignUpGenius auth: fetchproxy bridge is down (extension service worker unreachable after retry). ${downErr.hint}`);
|
|
158
|
+
}
|
|
153
159
|
const msg = e instanceof Error ? e.message : String(e);
|
|
154
160
|
throw new Error('SignUpGenius auth: no SIGNUPGENIUS_USER_KEY or SIGNUPGENIUS_EMAIL/PASSWORD set, ' +
|
|
155
161
|
`and fetchproxy fallback failed: ${msg}`);
|
package/dist/bundle.js
CHANGED
|
@@ -36014,6 +36014,52 @@ var FetchproxyHttpError = class extends Error {
|
|
|
36014
36014
|
this.name = "FetchproxyHttpError";
|
|
36015
36015
|
}
|
|
36016
36016
|
};
|
|
36017
|
+
var FetchproxyBridgeDownError = class extends FetchproxyProtocolError {
|
|
36018
|
+
originalError;
|
|
36019
|
+
retryAttempted;
|
|
36020
|
+
op;
|
|
36021
|
+
url;
|
|
36022
|
+
/** 0.8.0+: bridge role at throw time; `null` if listen() hadn't bound yet. */
|
|
36023
|
+
role;
|
|
36024
|
+
/** 0.8.0+: bridge port at throw time (the same port `listen()` bound to). */
|
|
36025
|
+
port;
|
|
36026
|
+
hint;
|
|
36027
|
+
constructor(args) {
|
|
36028
|
+
const retryAttempted = args.retryAttempted ?? false;
|
|
36029
|
+
const op = args.op ?? "fetch";
|
|
36030
|
+
const retryClause = retryAttempted ? `Server already burned a one-shot lazy-revive retry; SW is still down. ` : `Server lazy-revive retry was disabled (bridgeReviveDelayMs unset/0). `;
|
|
36031
|
+
const hint = `the fetchproxy extension's service worker is not responding ("${args.originalError}"). Chrome evicts extension service workers after ~30s idle by default. ${retryClause}Wake it by clicking the fetchproxy extension toolbar icon, then retry. If it keeps happening, reload the extension from chrome://extensions.`;
|
|
36032
|
+
super(`fetchproxy bridge down during ${op}${args.url ? ` (${args.url})` : ""}. ${hint}`);
|
|
36033
|
+
this.name = "FetchproxyBridgeDownError";
|
|
36034
|
+
this.originalError = args.originalError;
|
|
36035
|
+
this.retryAttempted = retryAttempted;
|
|
36036
|
+
this.op = op;
|
|
36037
|
+
if (args.url !== void 0)
|
|
36038
|
+
this.url = args.url;
|
|
36039
|
+
this.role = args.role ?? null;
|
|
36040
|
+
this.port = args.port ?? 0;
|
|
36041
|
+
this.hint = hint;
|
|
36042
|
+
}
|
|
36043
|
+
};
|
|
36044
|
+
var FetchproxyTimeoutError = class extends FetchproxyProtocolError {
|
|
36045
|
+
url;
|
|
36046
|
+
timeoutMs;
|
|
36047
|
+
/** 0.8.0+: bridge role at throw time; `null` if listen() hadn't bound yet. */
|
|
36048
|
+
role;
|
|
36049
|
+
/** 0.8.0+: bridge port at throw time. */
|
|
36050
|
+
port;
|
|
36051
|
+
/** 0.8.0+: actual elapsed milliseconds when the timer won the race. */
|
|
36052
|
+
elapsedMs;
|
|
36053
|
+
constructor(args) {
|
|
36054
|
+
super(`fetchproxy: ${args.url} did not respond within ${args.timeoutMs}ms`);
|
|
36055
|
+
this.name = "FetchproxyTimeoutError";
|
|
36056
|
+
this.url = args.url;
|
|
36057
|
+
this.timeoutMs = args.timeoutMs;
|
|
36058
|
+
this.role = args.role ?? null;
|
|
36059
|
+
this.port = args.port ?? 0;
|
|
36060
|
+
this.elapsedMs = args.elapsedMs ?? args.timeoutMs;
|
|
36061
|
+
}
|
|
36062
|
+
};
|
|
36017
36063
|
var SUBDOMAIN_LABEL_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
|
|
36018
36064
|
function assertSubdomainLabel(label) {
|
|
36019
36065
|
if (!SUBDOMAIN_LABEL_RE.test(label)) {
|
|
@@ -36051,6 +36097,18 @@ var FetchproxyServer = class {
|
|
|
36051
36097
|
hostHandle = null;
|
|
36052
36098
|
peerHandle = null;
|
|
36053
36099
|
nextRequestId = 1;
|
|
36100
|
+
// 0.8.0+: process-wide freshness counters surfaced via bridgeHealth().
|
|
36101
|
+
// Replaces the local copies every downstream MCP was rolling on top
|
|
36102
|
+
// of its own transport adapter — see realty-mcp cohort drift notes.
|
|
36103
|
+
// Updated by recordSuccess / recordFailure from fetch + capture paths.
|
|
36104
|
+
// `lastExtensionMessageAt` (#23 ask 4) is updated whenever any inner
|
|
36105
|
+
// frame from the extension arrives — gives extension-side liveness
|
|
36106
|
+
// distinct from per-call success/failure.
|
|
36107
|
+
lastSuccessAt = null;
|
|
36108
|
+
lastFailureAt = null;
|
|
36109
|
+
lastFailureReason = null;
|
|
36110
|
+
consecutiveFailures = 0;
|
|
36111
|
+
lastExtensionMessageAt = null;
|
|
36054
36112
|
pending = /* @__PURE__ */ new Map();
|
|
36055
36113
|
// Separate pending map for read_cookies so the response shape (cookies
|
|
36056
36114
|
// string vs status/body) doesn't have to share a union type with fetch.
|
|
@@ -36119,6 +36177,12 @@ var FetchproxyServer = class {
|
|
|
36119
36177
|
key: d.key,
|
|
36120
36178
|
jsonPointer: d.jsonPointer
|
|
36121
36179
|
})),
|
|
36180
|
+
// 0.8.0+: timer + lazy-revive default to ON. Every realty MCP
|
|
36181
|
+
// adapter was about to set these to the same numbers anyway; the
|
|
36182
|
+
// back-door is `0` (explicit opt-out) if a caller genuinely wants
|
|
36183
|
+
// the legacy hang-forever / fail-once-on-SW-eviction behavior.
|
|
36184
|
+
fetchTimeoutMs: opts.fetchTimeoutMs ?? 3e4,
|
|
36185
|
+
bridgeReviveDelayMs: opts.bridgeReviveDelayMs ?? 2e3,
|
|
36122
36186
|
identityDir: opts.identityDir,
|
|
36123
36187
|
onPairCode: opts.onPairCode
|
|
36124
36188
|
};
|
|
@@ -36254,7 +36318,7 @@ var FetchproxyServer = class {
|
|
|
36254
36318
|
}
|
|
36255
36319
|
}
|
|
36256
36320
|
pairingErrorMessage(code) {
|
|
36257
|
-
return `fetchproxy: pairing required for ${this.opts.serverName}
|
|
36321
|
+
return `fetchproxy transport error: pairing required for ${this.opts.serverName}. Tell the user to open the Transporter browser extension popup and approve the pair request. The pair code is: ${code} \u2014 display this code to the user so they can verify it matches.`;
|
|
36258
36322
|
}
|
|
36259
36323
|
/**
|
|
36260
36324
|
* Raw single-shot fetch through the bridge. Most callers should prefer
|
|
@@ -36275,8 +36339,71 @@ var FetchproxyServer = class {
|
|
|
36275
36339
|
const pendingCode = this.currentPendingPairCode();
|
|
36276
36340
|
if (pendingCode !== null) {
|
|
36277
36341
|
const error51 = this.pairingErrorMessage(pendingCode);
|
|
36278
|
-
return {
|
|
36342
|
+
return {
|
|
36343
|
+
ok: false,
|
|
36344
|
+
error: error51,
|
|
36345
|
+
kind: classifyFetchError(error51),
|
|
36346
|
+
retryAttempted: false
|
|
36347
|
+
};
|
|
36348
|
+
}
|
|
36349
|
+
const first = await this._fetchOnceWithTimeout(init);
|
|
36350
|
+
const reviveMs = this.opts.bridgeReviveDelayMs;
|
|
36351
|
+
let final = first;
|
|
36352
|
+
if (!first.ok && first.kind === "content_script_unreachable" && reviveMs !== void 0 && reviveMs > 0) {
|
|
36353
|
+
await new Promise((r) => setTimeout(r, reviveMs));
|
|
36354
|
+
const second = await this._fetchOnceWithTimeout(init);
|
|
36355
|
+
if (second.ok)
|
|
36356
|
+
this.recordSuccess();
|
|
36357
|
+
else
|
|
36358
|
+
this.recordFailure(`${second.kind ?? "other"}: ${second.error}`);
|
|
36359
|
+
return { ...second, retryAttempted: true };
|
|
36279
36360
|
}
|
|
36361
|
+
if (first.ok)
|
|
36362
|
+
this.recordSuccess();
|
|
36363
|
+
else
|
|
36364
|
+
this.recordFailure(`${first.kind ?? "other"}: ${first.error}`);
|
|
36365
|
+
return { ...first, retryAttempted: false };
|
|
36366
|
+
}
|
|
36367
|
+
/**
|
|
36368
|
+
* 0.8.0+: snapshot of the bridge's process-wide freshness counters,
|
|
36369
|
+
* suitable for surfacing through a downstream MCP's healthcheck tool.
|
|
36370
|
+
* Counters reset on a success (consecutiveFailures), accumulate
|
|
36371
|
+
* across the process lifetime otherwise. Replaces the per-MCP
|
|
36372
|
+
* duplication the realty cohort had been rolling in their adapters.
|
|
36373
|
+
* `lastExtensionMessageAt` is updated whenever ANY inner frame
|
|
36374
|
+
* arrives from the extension — gives extension-side liveness
|
|
36375
|
+
* distinct from server-side success/failure of the user-visible
|
|
36376
|
+
* call (addresses #23 ask 4).
|
|
36377
|
+
*/
|
|
36378
|
+
bridgeHealth() {
|
|
36379
|
+
return {
|
|
36380
|
+
role: this.role,
|
|
36381
|
+
port: this.opts.port,
|
|
36382
|
+
serverVersion: this.opts.version,
|
|
36383
|
+
fetchTimeoutMs: this.opts.fetchTimeoutMs ?? 0,
|
|
36384
|
+
bridgeReviveDelayMs: this.opts.bridgeReviveDelayMs ?? 0,
|
|
36385
|
+
lastSuccessAt: this.lastSuccessAt,
|
|
36386
|
+
lastFailureAt: this.lastFailureAt,
|
|
36387
|
+
lastFailureReason: this.lastFailureReason,
|
|
36388
|
+
consecutiveFailures: this.consecutiveFailures,
|
|
36389
|
+
lastExtensionMessageAt: this.lastExtensionMessageAt
|
|
36390
|
+
};
|
|
36391
|
+
}
|
|
36392
|
+
recordSuccess() {
|
|
36393
|
+
this.lastSuccessAt = Date.now();
|
|
36394
|
+
this.consecutiveFailures = 0;
|
|
36395
|
+
}
|
|
36396
|
+
recordFailure(reason) {
|
|
36397
|
+
this.lastFailureAt = Date.now();
|
|
36398
|
+
this.lastFailureReason = reason;
|
|
36399
|
+
this.consecutiveFailures += 1;
|
|
36400
|
+
}
|
|
36401
|
+
/**
|
|
36402
|
+
* Single bridge round-trip, wrapped by `fetchTimeoutMs` when set.
|
|
36403
|
+
* On timeout returns the `{ok:false, kind:'timeout'}` envelope —
|
|
36404
|
+
* the throwing surface is the convenience methods.
|
|
36405
|
+
*/
|
|
36406
|
+
async _fetchOnceWithTimeout(init) {
|
|
36280
36407
|
const id = this.nextRequestId++;
|
|
36281
36408
|
const inner = { type: "request", id, op: "fetch", init };
|
|
36282
36409
|
const pending = new Promise((resolve) => {
|
|
@@ -36287,7 +36414,61 @@ var FetchproxyServer = class {
|
|
|
36287
36414
|
} else if (this.peerHandle) {
|
|
36288
36415
|
await this.peerHandle.sendInner(inner);
|
|
36289
36416
|
}
|
|
36290
|
-
|
|
36417
|
+
const timeoutMs = this.opts.fetchTimeoutMs;
|
|
36418
|
+
if (timeoutMs === void 0 || timeoutMs <= 0)
|
|
36419
|
+
return pending;
|
|
36420
|
+
let timer;
|
|
36421
|
+
const start = Date.now();
|
|
36422
|
+
try {
|
|
36423
|
+
return await Promise.race([
|
|
36424
|
+
pending,
|
|
36425
|
+
new Promise((resolve) => {
|
|
36426
|
+
timer = setTimeout(() => {
|
|
36427
|
+
this.pending.delete(id);
|
|
36428
|
+
const elapsedMs = Date.now() - start;
|
|
36429
|
+
const error51 = `fetchproxy: ${init.url} did not respond within ${timeoutMs}ms`;
|
|
36430
|
+
resolve({
|
|
36431
|
+
ok: false,
|
|
36432
|
+
error: error51,
|
|
36433
|
+
kind: "timeout",
|
|
36434
|
+
retryAttempted: false,
|
|
36435
|
+
elapsedMs
|
|
36436
|
+
});
|
|
36437
|
+
}, timeoutMs);
|
|
36438
|
+
})
|
|
36439
|
+
]);
|
|
36440
|
+
} finally {
|
|
36441
|
+
if (timer)
|
|
36442
|
+
clearTimeout(timer);
|
|
36443
|
+
}
|
|
36444
|
+
}
|
|
36445
|
+
/**
|
|
36446
|
+
* Map an `ok:false` fetch result to its typed throwable. Centralizes
|
|
36447
|
+
* the kind-to-error-class switch so `request()` and (via the same
|
|
36448
|
+
* logic re-implemented inline) `captureRequestHeader()` agree on what
|
|
36449
|
+
* to throw.
|
|
36450
|
+
*/
|
|
36451
|
+
_typedErrorFor(result, url2, op, retryAttempted) {
|
|
36452
|
+
if (result.kind === "timeout") {
|
|
36453
|
+
return new FetchproxyTimeoutError({
|
|
36454
|
+
url: url2,
|
|
36455
|
+
timeoutMs: this.opts.fetchTimeoutMs ?? 0,
|
|
36456
|
+
role: this.role,
|
|
36457
|
+
port: this.opts.port,
|
|
36458
|
+
elapsedMs: result.elapsedMs
|
|
36459
|
+
});
|
|
36460
|
+
}
|
|
36461
|
+
if (result.kind === "content_script_unreachable") {
|
|
36462
|
+
return new FetchproxyBridgeDownError({
|
|
36463
|
+
originalError: result.error,
|
|
36464
|
+
retryAttempted,
|
|
36465
|
+
op,
|
|
36466
|
+
url: url2,
|
|
36467
|
+
role: this.role,
|
|
36468
|
+
port: this.opts.port
|
|
36469
|
+
});
|
|
36470
|
+
}
|
|
36471
|
+
return new FetchproxyProtocolError(result.error);
|
|
36291
36472
|
}
|
|
36292
36473
|
/**
|
|
36293
36474
|
* Convenience wrapper around `fetch()`. Builds the URL from a path
|
|
@@ -36310,8 +36491,18 @@ var FetchproxyServer = class {
|
|
|
36310
36491
|
if (opts.subdomain !== void 0)
|
|
36311
36492
|
assertSubdomainLabel(opts.subdomain);
|
|
36312
36493
|
const baseDomain = this.resolveBaseDomain(opts.domain);
|
|
36313
|
-
const
|
|
36314
|
-
|
|
36494
|
+
const isAbsolute = path.startsWith("http://") || path.startsWith("https://");
|
|
36495
|
+
let host;
|
|
36496
|
+
if (isAbsolute) {
|
|
36497
|
+
try {
|
|
36498
|
+
host = new URL(path).host;
|
|
36499
|
+
} catch {
|
|
36500
|
+
throw new Error(`FetchproxyServer.request: absolute path is not a valid URL: ${JSON.stringify(path)}`);
|
|
36501
|
+
}
|
|
36502
|
+
} else {
|
|
36503
|
+
host = opts.subdomain ? `${opts.subdomain}.${baseDomain}` : baseDomain;
|
|
36504
|
+
}
|
|
36505
|
+
const url2 = isAbsolute ? path : `https://${host}${path}`;
|
|
36315
36506
|
assertUrlInDomains("request url", url2, this.opts.domains);
|
|
36316
36507
|
const init = {
|
|
36317
36508
|
url: url2,
|
|
@@ -36322,7 +36513,7 @@ var FetchproxyServer = class {
|
|
|
36322
36513
|
};
|
|
36323
36514
|
const result = await this.fetch(init);
|
|
36324
36515
|
if (!result.ok) {
|
|
36325
|
-
throw
|
|
36516
|
+
throw this._typedErrorFor(result, init.url, "fetch", result.retryAttempted ?? false);
|
|
36326
36517
|
}
|
|
36327
36518
|
const response = {
|
|
36328
36519
|
status: result.status,
|
|
@@ -36532,10 +36723,73 @@ var FetchproxyServer = class {
|
|
|
36532
36723
|
}
|
|
36533
36724
|
await this.ensureConnected();
|
|
36534
36725
|
this.throwIfPendingPair();
|
|
36535
|
-
const
|
|
36536
|
-
|
|
36537
|
-
|
|
36726
|
+
const decls = this.opts.captureHeaders;
|
|
36727
|
+
let resolved;
|
|
36728
|
+
if (opts?.urlPattern !== void 0 && opts?.headerName !== void 0) {
|
|
36729
|
+
const found = decls.find((d) => d.urlPattern === opts.urlPattern && d.headerName === opts.headerName);
|
|
36730
|
+
if (!found) {
|
|
36731
|
+
throw new Error(`FetchproxyServer.captureRequestHeader: (urlPattern=${JSON.stringify(opts.urlPattern)}, headerName=${JSON.stringify(opts.headerName)}) not declared in captureHeaders`);
|
|
36732
|
+
}
|
|
36733
|
+
resolved = found;
|
|
36734
|
+
} else if (opts?.urlPattern === void 0 && opts?.headerName === void 0) {
|
|
36735
|
+
if (decls.length === 0) {
|
|
36736
|
+
throw new Error("FetchproxyServer.captureRequestHeader: no captureHeaders declared on this server \u2014 declare at least one entry in FetchproxyServerOpts.captureHeaders, or pass {urlPattern, headerName} explicitly");
|
|
36737
|
+
}
|
|
36738
|
+
if (decls.length > 1) {
|
|
36739
|
+
const list = decls.map((d) => `${JSON.stringify(d.urlPattern)}/${JSON.stringify(d.headerName)}`).join(", ");
|
|
36740
|
+
throw new Error(`FetchproxyServer.captureRequestHeader: multiple captureHeaders declared (${decls.length}: ${list}); pass {urlPattern, headerName} to disambiguate`);
|
|
36741
|
+
}
|
|
36742
|
+
resolved = decls[0];
|
|
36743
|
+
} else {
|
|
36744
|
+
throw new Error("FetchproxyServer.captureRequestHeader: pass both urlPattern AND headerName, or neither (which defaults to the single declared entry)");
|
|
36538
36745
|
}
|
|
36746
|
+
const callOpts = { ...resolved, ...opts?.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {} };
|
|
36747
|
+
try {
|
|
36748
|
+
const result = await this._captureRequestHeaderOnce(callOpts);
|
|
36749
|
+
this.recordSuccess();
|
|
36750
|
+
return result;
|
|
36751
|
+
} catch (err) {
|
|
36752
|
+
const swDown = err instanceof FetchproxyProtocolError && classifyFetchError(err.message) === "content_script_unreachable";
|
|
36753
|
+
if (!swDown) {
|
|
36754
|
+
this.recordFailure(`capture_request_header: ${err.message ?? String(err)}`);
|
|
36755
|
+
throw err;
|
|
36756
|
+
}
|
|
36757
|
+
const reviveMs = this.opts.bridgeReviveDelayMs ?? 0;
|
|
36758
|
+
if (reviveMs > 0) {
|
|
36759
|
+
await new Promise((r) => setTimeout(r, reviveMs));
|
|
36760
|
+
try {
|
|
36761
|
+
const result = await this._captureRequestHeaderOnce(callOpts);
|
|
36762
|
+
this.recordSuccess();
|
|
36763
|
+
return result;
|
|
36764
|
+
} catch (retryErr) {
|
|
36765
|
+
const stillDown = retryErr instanceof FetchproxyProtocolError && classifyFetchError(retryErr.message) === "content_script_unreachable";
|
|
36766
|
+
if (!stillDown) {
|
|
36767
|
+
this.recordFailure(`capture_request_header: ${retryErr.message ?? String(retryErr)}`);
|
|
36768
|
+
throw retryErr;
|
|
36769
|
+
}
|
|
36770
|
+
this.recordFailure(`capture_request_header bridge-down: ${retryErr.message}`);
|
|
36771
|
+
throw new FetchproxyBridgeDownError({
|
|
36772
|
+
originalError: retryErr.message,
|
|
36773
|
+
retryAttempted: true,
|
|
36774
|
+
op: "capture_request_header",
|
|
36775
|
+
url: resolved.urlPattern,
|
|
36776
|
+
role: this.role,
|
|
36777
|
+
port: this.opts.port
|
|
36778
|
+
});
|
|
36779
|
+
}
|
|
36780
|
+
}
|
|
36781
|
+
this.recordFailure(`capture_request_header bridge-down: ${err.message}`);
|
|
36782
|
+
throw new FetchproxyBridgeDownError({
|
|
36783
|
+
originalError: err.message,
|
|
36784
|
+
retryAttempted: false,
|
|
36785
|
+
op: "capture_request_header",
|
|
36786
|
+
url: resolved.urlPattern,
|
|
36787
|
+
role: this.role,
|
|
36788
|
+
port: this.opts.port
|
|
36789
|
+
});
|
|
36790
|
+
}
|
|
36791
|
+
}
|
|
36792
|
+
async _captureRequestHeaderOnce(opts) {
|
|
36539
36793
|
const id = this.nextRequestId++;
|
|
36540
36794
|
const inner = {
|
|
36541
36795
|
type: "request",
|
|
@@ -36644,18 +36898,35 @@ var FetchproxyServer = class {
|
|
|
36644
36898
|
onInner(inner) {
|
|
36645
36899
|
if (inner.type !== "response")
|
|
36646
36900
|
return;
|
|
36901
|
+
this.lastExtensionMessageAt = Date.now();
|
|
36647
36902
|
const fetchCb = this.pending.get(inner.id);
|
|
36648
36903
|
if (fetchCb) {
|
|
36649
36904
|
this.pending.delete(inner.id);
|
|
36650
36905
|
if (inner.ok) {
|
|
36651
36906
|
if (inner.op === void 0 || inner.op === "fetch") {
|
|
36652
|
-
fetchCb({
|
|
36907
|
+
fetchCb({
|
|
36908
|
+
ok: true,
|
|
36909
|
+
status: inner.status,
|
|
36910
|
+
url: inner.url,
|
|
36911
|
+
body: inner.body,
|
|
36912
|
+
retryAttempted: false
|
|
36913
|
+
});
|
|
36653
36914
|
} else {
|
|
36654
36915
|
const error51 = `unexpected ${inner.op} response on fetch awaiter`;
|
|
36655
|
-
fetchCb({
|
|
36916
|
+
fetchCb({
|
|
36917
|
+
ok: false,
|
|
36918
|
+
error: error51,
|
|
36919
|
+
kind: classifyFetchError(error51),
|
|
36920
|
+
retryAttempted: false
|
|
36921
|
+
});
|
|
36656
36922
|
}
|
|
36657
36923
|
} else {
|
|
36658
|
-
fetchCb({
|
|
36924
|
+
fetchCb({
|
|
36925
|
+
ok: false,
|
|
36926
|
+
error: inner.error,
|
|
36927
|
+
kind: classifyFetchError(inner.error),
|
|
36928
|
+
retryAttempted: false
|
|
36929
|
+
});
|
|
36659
36930
|
}
|
|
36660
36931
|
return;
|
|
36661
36932
|
}
|
|
@@ -36725,7 +36996,12 @@ var FetchproxyServer = class {
|
|
|
36725
36996
|
rejectAllPending(reason = "extension disconnected") {
|
|
36726
36997
|
const err = new FetchproxyProtocolError(reason);
|
|
36727
36998
|
for (const cb of this.pending.values()) {
|
|
36728
|
-
cb({
|
|
36999
|
+
cb({
|
|
37000
|
+
ok: false,
|
|
37001
|
+
error: err.message,
|
|
37002
|
+
kind: classifyFetchError(err.message),
|
|
37003
|
+
retryAttempted: false
|
|
37004
|
+
});
|
|
36729
37005
|
}
|
|
36730
37006
|
this.pending.clear();
|
|
36731
37007
|
for (const cb of this.pendingReadCookies.values()) {
|
|
@@ -36790,6 +37066,19 @@ var FetchproxyServer = class {
|
|
|
36790
37066
|
}
|
|
36791
37067
|
};
|
|
36792
37068
|
|
|
37069
|
+
// node_modules/@fetchproxy/server/dist/classify-bridge-error.js
|
|
37070
|
+
function classifyBridgeError(err) {
|
|
37071
|
+
if (err instanceof FetchproxyTimeoutError)
|
|
37072
|
+
return "timeout";
|
|
37073
|
+
if (err instanceof FetchproxyBridgeDownError)
|
|
37074
|
+
return "bridge_down";
|
|
37075
|
+
if (err instanceof FetchproxyHttpError)
|
|
37076
|
+
return "http";
|
|
37077
|
+
if (err instanceof FetchproxyProtocolError)
|
|
37078
|
+
return "protocol";
|
|
37079
|
+
return "other";
|
|
37080
|
+
}
|
|
37081
|
+
|
|
36793
37082
|
// node_modules/@fetchproxy/bootstrap/dist/index.js
|
|
36794
37083
|
var defaultFactory = (opts) => new FetchproxyServer(opts);
|
|
36795
37084
|
async function bootstrap(opts) {
|
|
@@ -36844,7 +37133,11 @@ async function bootstrap(opts) {
|
|
|
36844
37133
|
key: p.storageKey,
|
|
36845
37134
|
jsonPointer: p.jsonPointer
|
|
36846
37135
|
})),
|
|
36847
|
-
onPairCode: opts.onPairCode
|
|
37136
|
+
onPairCode: opts.onPairCode,
|
|
37137
|
+
// 0.8.0+ pass-through. Only forwarded when the caller set them;
|
|
37138
|
+
// unset → server defaults apply (30000 / 2000 in 0.8.0).
|
|
37139
|
+
...opts.fetchTimeoutMs !== void 0 ? { fetchTimeoutMs: opts.fetchTimeoutMs } : {},
|
|
37140
|
+
...opts.bridgeReviveDelayMs !== void 0 ? { bridgeReviveDelayMs: opts.bridgeReviveDelayMs } : {}
|
|
36848
37141
|
});
|
|
36849
37142
|
const storageDomainOpts = {};
|
|
36850
37143
|
if (opts.storageDomain !== void 0)
|
|
@@ -37023,7 +37316,7 @@ function loadAccount(env = process.env) {
|
|
|
37023
37316
|
// package.json
|
|
37024
37317
|
var package_default = {
|
|
37025
37318
|
name: "signupgenius-mcp",
|
|
37026
|
-
version: "1.
|
|
37319
|
+
version: "1.1.1",
|
|
37027
37320
|
mcpName: "io.github.chrischall/signupgenius-mcp",
|
|
37028
37321
|
description: "SignUpGenius MCP server \u2014 read sign-ups, reports, and groups; add group members.",
|
|
37029
37322
|
author: "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -37060,7 +37353,8 @@ var package_default = {
|
|
|
37060
37353
|
"test:watch": "vitest"
|
|
37061
37354
|
},
|
|
37062
37355
|
dependencies: {
|
|
37063
|
-
"@fetchproxy/bootstrap": "^0.
|
|
37356
|
+
"@fetchproxy/bootstrap": "^0.8.0",
|
|
37357
|
+
"@fetchproxy/server": "^0.8.0",
|
|
37064
37358
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
37065
37359
|
dotenv: "^17.4.2",
|
|
37066
37360
|
zod: "^4.4.3"
|
|
@@ -37145,6 +37439,12 @@ async function resolveAuth() {
|
|
|
37145
37439
|
source: "fetchproxy"
|
|
37146
37440
|
};
|
|
37147
37441
|
} catch (e) {
|
|
37442
|
+
if (classifyBridgeError(e) === "bridge_down") {
|
|
37443
|
+
const downErr = e;
|
|
37444
|
+
throw new Error(
|
|
37445
|
+
`SignUpGenius auth: fetchproxy bridge is down (extension service worker unreachable after retry). ${downErr.hint}`
|
|
37446
|
+
);
|
|
37447
|
+
}
|
|
37148
37448
|
const msg = e instanceof Error ? e.message : String(e);
|
|
37149
37449
|
throw new Error(
|
|
37150
37450
|
`SignUpGenius auth: no SIGNUPGENIUS_USER_KEY or SIGNUPGENIUS_EMAIL/PASSWORD set, and fetchproxy fallback failed: ${msg}`
|
|
@@ -37974,7 +38274,7 @@ var client = new SignUpGeniusClient(account, {
|
|
|
37974
38274
|
configError: configError ?? void 0,
|
|
37975
38275
|
preloaded
|
|
37976
38276
|
});
|
|
37977
|
-
var server = new McpServer({ name: "signupgenius", version: "1.
|
|
38277
|
+
var server = new McpServer({ name: "signupgenius", version: "1.1.1" });
|
|
37978
38278
|
registerUserTools(server, client);
|
|
37979
38279
|
registerGroupTools(server, client);
|
|
37980
38280
|
registerSignUpTools(server, client);
|
package/dist/index.js
CHANGED
|
@@ -43,7 +43,7 @@ const client = new SignUpGeniusClient(account, {
|
|
|
43
43
|
configError: configError ?? undefined,
|
|
44
44
|
preloaded,
|
|
45
45
|
});
|
|
46
|
-
const server = new McpServer({ name: 'signupgenius', version: '1.
|
|
46
|
+
const server = new McpServer({ name: 'signupgenius', version: '1.1.1' }); // x-release-please-version
|
|
47
47
|
registerUserTools(server, client);
|
|
48
48
|
registerGroupTools(server, client);
|
|
49
49
|
registerSignUpTools(server, client);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "signupgenius-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"mcpName": "io.github.chrischall/signupgenius-mcp",
|
|
5
5
|
"description": "SignUpGenius MCP server — read sign-ups, reports, and groups; add group members.",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"test:watch": "vitest"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@fetchproxy/bootstrap": "^0.
|
|
40
|
+
"@fetchproxy/bootstrap": "^0.8.0",
|
|
41
|
+
"@fetchproxy/server": "^0.8.0",
|
|
41
42
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
42
43
|
"dotenv": "^17.4.2",
|
|
43
44
|
"zod": "^4.4.3"
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/chrischall/signupgenius-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.1.1",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "signupgenius-mcp",
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.1.1",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|