signupgenius-mcp 1.1.3 → 1.1.5

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.
@@ -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.1.3"
10
+ "version": "1.1.5"
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.1.3",
18
+ "version": "1.1.5",
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.1.3",
4
+ "version": "1.1.5",
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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chris Hall
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # signupgenius-mcp
2
2
 
3
+ [![CI](https://github.com/chrischall/signupgenius-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/chrischall/signupgenius-mcp/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/signupgenius-mcp)](https://www.npmjs.com/package/signupgenius-mcp)
5
+ [![license](https://img.shields.io/npm/l/signupgenius-mcp)](LICENSE)
6
+
3
7
  MCP server for [SignUpGenius](https://www.signupgenius.com). 13 read tools and 1 write across profile, groups, sign-ups, and reports.
4
8
 
5
9
  Three auth modes (tried in this priority order — first match wins):
package/dist/bundle.js CHANGED
@@ -13,7 +13,11 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
13
13
  throw Error('Dynamic require of "' + x + '" is not supported');
14
14
  });
15
15
  var __commonJS = (cb, mod) => function __require2() {
16
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
16
+ try {
17
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18
+ } catch (e) {
19
+ throw mod = 0, e;
20
+ }
17
21
  };
18
22
  var __export = (target, all) => {
19
23
  for (var name in all)
@@ -35860,10 +35864,20 @@ async function openEncryptedFrame(sessionKey, frame) {
35860
35864
 
35861
35865
  // node_modules/@fetchproxy/server/dist/election.js
35862
35866
  import { createServer, Server as HttpServer } from "node:http";
35867
+ var DEFAULT_BIND_TIMEOUT_MS = 5e3;
35863
35868
  async function electRole(opts) {
35864
35869
  const server = createServer();
35870
+ const bindTimeoutMs = opts.bindTimeoutMs ?? DEFAULT_BIND_TIMEOUT_MS;
35865
35871
  return new Promise((resolve, reject) => {
35872
+ let timer;
35873
+ const clearBindTimer = () => {
35874
+ if (timer) {
35875
+ clearTimeout(timer);
35876
+ timer = void 0;
35877
+ }
35878
+ };
35866
35879
  const onError = (e) => {
35880
+ clearBindTimer();
35867
35881
  server.removeListener("listening", onListening);
35868
35882
  if (e.code === "EADDRINUSE") {
35869
35883
  try {
@@ -35876,11 +35890,25 @@ async function electRole(opts) {
35876
35890
  }
35877
35891
  };
35878
35892
  const onListening = () => {
35893
+ clearBindTimer();
35879
35894
  server.removeListener("error", onError);
35880
35895
  resolve({ role: "host", server });
35881
35896
  };
35882
35897
  server.once("error", onError);
35883
35898
  server.once("listening", onListening);
35899
+ if (bindTimeoutMs > 0) {
35900
+ timer = setTimeout(() => {
35901
+ server.removeListener("error", onError);
35902
+ server.removeListener("listening", onListening);
35903
+ try {
35904
+ server.close();
35905
+ } catch {
35906
+ }
35907
+ reject(new Error(`fetchproxy: bind to ${opts.host}:${opts.port} timed out after ${bindTimeoutMs}ms (port may be in a bad state)`));
35908
+ }, bindTimeoutMs);
35909
+ if (typeof timer.unref === "function")
35910
+ timer.unref();
35911
+ }
35884
35912
  server.listen(opts.port, opts.host);
35885
35913
  });
35886
35914
  }
@@ -35973,6 +36001,44 @@ var SessionState = class {
35973
36001
  }
35974
36002
  };
35975
36003
 
36004
+ // node_modules/@fetchproxy/server/dist/session-ready.js
36005
+ var SESSION_READY_TIMEOUT_MS = 3e4;
36006
+ var FetchproxySessionNotReadyError = class extends Error {
36007
+ reason;
36008
+ pairCode;
36009
+ mcpId;
36010
+ hint;
36011
+ constructor(info) {
36012
+ const pairing = info.pairCode !== null && info.pairCode !== "";
36013
+ const hint = pairing ? `Open the Transporter extension popup and approve pair code ${info.pairCode} for "${info.mcpId}", then retry.` : `The extension is connected but hasn't confirmed a session for "${info.mcpId}" \u2014 sign in to the target site in that browser (and approve the requested scope if it changed), then retry.`;
36014
+ super(`fetchproxy: ${pairing ? "pairing not yet approved" : "no confirmed browser session"} for "${info.mcpId}". ${hint}`);
36015
+ this.name = "FetchproxySessionNotReadyError";
36016
+ this.reason = pairing ? "pair-required" : "not-ready";
36017
+ this.pairCode = pairing ? info.pairCode : null;
36018
+ this.mcpId = info.mcpId;
36019
+ this.hint = hint;
36020
+ Object.setPrototypeOf(this, new.target.prototype);
36021
+ }
36022
+ };
36023
+ async function awaitSessionReady(ready, opts) {
36024
+ const ms = opts.timeoutMs ?? SESSION_READY_TIMEOUT_MS;
36025
+ if (ms <= 0)
36026
+ return ready;
36027
+ let timer;
36028
+ const timeout = new Promise((_, reject) => {
36029
+ timer = setTimeout(() => {
36030
+ reject(new FetchproxySessionNotReadyError({ mcpId: opts.mcpId, pairCode: opts.pendingPairCode() }));
36031
+ }, ms);
36032
+ timer.unref?.();
36033
+ });
36034
+ try {
36035
+ return await Promise.race([ready, timeout]);
36036
+ } finally {
36037
+ if (timer)
36038
+ clearTimeout(timer);
36039
+ }
36040
+ }
36041
+
35976
36042
  // node_modules/@fetchproxy/server/dist/host.js
35977
36043
  var PUBLIC_ORIGIN_RE = /^https?:\/\/(?!(127\.0\.0\.1|localhost)(:|$))/i;
35978
36044
  var enc2 = new TextEncoder();
@@ -36060,6 +36126,29 @@ async function startHost(opts) {
36060
36126
  return;
36061
36127
  }
36062
36128
  if (frame.type === "hello" && frame.role === "server") {
36129
+ const peerEdPub = fromB64(frame.identityEd25519Pub);
36130
+ const peerSigMsg = concatBytes(enc2.encode(frame.mcpId), fromB64(frame.sessionNonce));
36131
+ const peerSig = fromB64(frame.sessionSig);
36132
+ let peerSigOk = false;
36133
+ try {
36134
+ peerSigOk = await ed25519Verify(peerEdPub, peerSigMsg, peerSig);
36135
+ } catch {
36136
+ peerSigOk = false;
36137
+ }
36138
+ if (!peerSigOk) {
36139
+ console.warn("[fetchproxy] peer hello signature invalid \u2014 refusing registration (possible squatter)");
36140
+ ws.close(1008, "peer hello signature invalid");
36141
+ return;
36142
+ }
36143
+ const existing = peers.get(frame.mcpId);
36144
+ if (existing && existing.ws !== ws) {
36145
+ const existingEdPub = existing.helloFrame.identityEd25519Pub;
36146
+ if (existingEdPub !== frame.identityEd25519Pub) {
36147
+ console.warn("[fetchproxy] peer mcpId already mapped to a different identity \u2014 refusing (mcpId squatting)");
36148
+ ws.close(1008, "mcpId already registered to another identity");
36149
+ return;
36150
+ }
36151
+ }
36063
36152
  identified = "peer";
36064
36153
  peerMcpId = frame.mcpId;
36065
36154
  peers.set(frame.mcpId, { ws, helloFrame: frame });
@@ -36152,8 +36241,10 @@ async function startHost(opts) {
36152
36241
  resetSessionPromise();
36153
36242
  disconnectListeners.forEach((cb) => cb());
36154
36243
  }
36155
- if (identified === "peer" && peerMcpId)
36156
- peers.delete(peerMcpId);
36244
+ if (identified === "peer" && peerMcpId) {
36245
+ if (peers.get(peerMcpId)?.ws === ws)
36246
+ peers.delete(peerMcpId);
36247
+ }
36157
36248
  });
36158
36249
  });
36159
36250
  return {
@@ -36169,7 +36260,10 @@ async function startHost(opts) {
36169
36260
  });
36170
36261
  }),
36171
36262
  sendOwnInner: async (inner) => {
36172
- const session = await ownSessionReady;
36263
+ const session = await awaitSessionReady(ownSessionReady, {
36264
+ mcpId: opts.ownMcpId,
36265
+ pendingPairCode: () => ownPendingPairCode
36266
+ });
36173
36267
  if (!extensionWs)
36174
36268
  throw new Error("host: no extension connected");
36175
36269
  const sealed = await sealInnerFrame(session.sessionKey, opts.ownMcpId, session.nextOutboundSeq(), inner);
@@ -36274,7 +36368,10 @@ async function startPeer(opts) {
36274
36368
  ws,
36275
36369
  session: sessionPromise,
36276
36370
  sendInner: async (inner) => {
36277
- await sessionPromise;
36371
+ await awaitSessionReady(sessionPromise, {
36372
+ mcpId: opts.mcpId,
36373
+ pendingPairCode: () => pendingPairCode
36374
+ });
36278
36375
  const s = session;
36279
36376
  const sealed = await sealInnerFrame(s.sessionKey, opts.mcpId, s.nextOutboundSeq(), inner);
36280
36377
  ws.send(JSON.stringify(sealed));
@@ -36940,6 +37037,35 @@ var FetchproxyServer = class {
36940
37037
  this.keepAliveTimer = null;
36941
37038
  }
36942
37039
  }
37040
+ /**
37041
+ * Send an inner request frame via whichever bridge handle is active. If the
37042
+ * send throws (e.g. `FetchproxySessionNotReadyError` — the session never
37043
+ * confirmed), the frame never reached the bridge, so no reply will arrive:
37044
+ * drop the just-registered pending resolver for this id (it lives in exactly
37045
+ * one of the op maps — request ids are unique) so it doesn't leak until the
37046
+ * server closes, then rethrow.
37047
+ */
37048
+ async sendInnerFrame(inner) {
37049
+ try {
37050
+ if (this.hostHandle) {
37051
+ await this.hostHandle.sendOwnInner(inner);
37052
+ } else if (this.peerHandle) {
37053
+ await this.peerHandle.sendInner(inner);
37054
+ }
37055
+ } catch (err) {
37056
+ if ("id" in inner && typeof inner.id === "number") {
37057
+ const { id } = inner;
37058
+ this.pending.delete(id);
37059
+ this.pendingReadCookies.delete(id);
37060
+ this.pendingStorage.delete(id);
37061
+ this.pendingCapture.delete(id);
37062
+ this.pendingRedirect.delete(id);
37063
+ this.pendingDownload.delete(id);
37064
+ this.pendingIdb.delete(id);
37065
+ }
37066
+ throw err;
37067
+ }
37068
+ }
36943
37069
  /**
36944
37070
  * Single bridge round-trip, wrapped by `fetchTimeoutMs` when set.
36945
37071
  * On timeout returns the `{ok:false, kind:'timeout'}` envelope —
@@ -36951,11 +37077,7 @@ var FetchproxyServer = class {
36951
37077
  const pending = new Promise((resolve) => {
36952
37078
  this.pending.set(id, resolve);
36953
37079
  });
36954
- if (this.hostHandle) {
36955
- await this.hostHandle.sendOwnInner(inner);
36956
- } else if (this.peerHandle) {
36957
- await this.peerHandle.sendInner(inner);
36958
- }
37080
+ await this.sendInnerFrame(inner);
36959
37081
  const timeoutMs = this.opts.fetchTimeoutMs;
36960
37082
  if (timeoutMs === void 0 || timeoutMs <= 0)
36961
37083
  return pending;
@@ -36984,6 +37106,51 @@ var FetchproxyServer = class {
36984
37106
  clearTimeout(timer);
36985
37107
  }
36986
37108
  }
37109
+ /**
37110
+ * FP-B2: bound a non-`fetch` verb's reply wait by `fetchTimeoutMs`.
37111
+ *
37112
+ * Before this, only `fetch()` raced its `pending` reply against a timer
37113
+ * (`_fetchOnceWithTimeout`); `readCookies`, the storage reads,
37114
+ * `capture_request_header`, `capture_redirect`, `download`, and
37115
+ * `read_indexed_db` awaited their `pending` promise with no race, so a
37116
+ * wedged extension hung the tool call indefinitely.
37117
+ *
37118
+ * `pending` is the already-registered reply promise. `pendingMap`/`id`
37119
+ * point at the op-specific map entry so we can drop it on expiry exactly
37120
+ * as `_fetchOnceWithTimeout` does — otherwise a late bridge reply would
37121
+ * resolve into a stale resolver / leak. On timeout we reject with a
37122
+ * `FetchproxyTimeoutError` (the same throwable the convenience methods
37123
+ * already surface for fetch timeouts). `0`/unset opts out (unbounded),
37124
+ * matching the fetch path.
37125
+ */
37126
+ async _withVerbTimeout(pending, pendingMap, id, url2) {
37127
+ const timeoutMs = this.opts.fetchTimeoutMs;
37128
+ if (timeoutMs === void 0 || timeoutMs <= 0)
37129
+ return pending;
37130
+ let timer;
37131
+ const start = Date.now();
37132
+ try {
37133
+ return await Promise.race([
37134
+ pending,
37135
+ new Promise((_resolve, reject) => {
37136
+ timer = setTimeout(() => {
37137
+ pendingMap.delete(id);
37138
+ reject(new FetchproxyTimeoutError({
37139
+ url: url2,
37140
+ timeoutMs,
37141
+ role: this.role,
37142
+ port: this.opts.port,
37143
+ elapsedMs: Date.now() - start,
37144
+ retryAttempted: false
37145
+ }));
37146
+ }, timeoutMs);
37147
+ })
37148
+ ]);
37149
+ } finally {
37150
+ if (timer)
37151
+ clearTimeout(timer);
37152
+ }
37153
+ }
36987
37154
  /**
36988
37155
  * Map an `ok:false` fetch result to its typed throwable. Centralizes
36989
37156
  * the kind-to-error-class switch so `request()` and (via the same
@@ -37274,12 +37441,8 @@ var FetchproxyServer = class {
37274
37441
  const pending = new Promise((resolve) => {
37275
37442
  this.pendingReadCookies.set(id, resolve);
37276
37443
  });
37277
- if (this.hostHandle) {
37278
- await this.hostHandle.sendOwnInner(inner);
37279
- } else if (this.peerHandle) {
37280
- await this.peerHandle.sendInner(inner);
37281
- }
37282
- const result = await pending;
37444
+ await this.sendInnerFrame(inner);
37445
+ const result = await this._withVerbTimeout(pending, this.pendingReadCookies, id, `https://${host}`);
37283
37446
  if (!result.ok) {
37284
37447
  throw new FetchproxyProtocolError(result.error);
37285
37448
  }
@@ -37345,12 +37508,8 @@ var FetchproxyServer = class {
37345
37508
  const pending = new Promise((resolve, reject) => {
37346
37509
  this.pendingStorage.set(id, { resolve, reject });
37347
37510
  });
37348
- if (this.hostHandle) {
37349
- await this.hostHandle.sendOwnInner(inner);
37350
- } else if (this.peerHandle) {
37351
- await this.peerHandle.sendInner(inner);
37352
- }
37353
- return pending;
37511
+ await this.sendInnerFrame(inner);
37512
+ return this._withVerbTimeout(pending, this.pendingStorage, id, `https://${host}`);
37354
37513
  }
37355
37514
  /**
37356
37515
  * 0.3.0+: snapshot the next outgoing request's named header. Single-
@@ -37454,12 +37613,8 @@ var FetchproxyServer = class {
37454
37613
  const pending = new Promise((resolve, reject) => {
37455
37614
  this.pendingCapture.set(id, { resolve, reject });
37456
37615
  });
37457
- if (this.hostHandle) {
37458
- await this.hostHandle.sendOwnInner(inner);
37459
- } else if (this.peerHandle) {
37460
- await this.peerHandle.sendInner(inner);
37461
- }
37462
- return pending;
37616
+ await this.sendInnerFrame(inner);
37617
+ return this._withVerbTimeout(pending, this.pendingCapture, id, `https://${opts.host}${opts.path ?? "/*"}`);
37463
37618
  }
37464
37619
  /**
37465
37620
  * Snapshot the redirect target URL of the next request the browser
@@ -37543,12 +37698,8 @@ var FetchproxyServer = class {
37543
37698
  const pending = new Promise((resolve, reject) => {
37544
37699
  this.pendingRedirect.set(id, { resolve, reject });
37545
37700
  });
37546
- if (this.hostHandle) {
37547
- await this.hostHandle.sendOwnInner(inner);
37548
- } else if (this.peerHandle) {
37549
- await this.peerHandle.sendInner(inner);
37550
- }
37551
- return pending;
37701
+ await this.sendInnerFrame(inner);
37702
+ return this._withVerbTimeout(pending, this.pendingRedirect, id, `https://${opts.host}${opts.path ?? "/*"}`);
37552
37703
  }
37553
37704
  /**
37554
37705
  * Download `url` through the BROWSER's own network stack via
@@ -37629,12 +37780,8 @@ var FetchproxyServer = class {
37629
37780
  const pending = new Promise((resolve, reject) => {
37630
37781
  this.pendingDownload.set(id, { resolve, reject });
37631
37782
  });
37632
- if (this.hostHandle) {
37633
- await this.hostHandle.sendOwnInner(inner);
37634
- } else if (this.peerHandle) {
37635
- await this.peerHandle.sendInner(inner);
37636
- }
37637
- return pending;
37783
+ await this.sendInnerFrame(inner);
37784
+ return this._withVerbTimeout(pending, this.pendingDownload, id, opts.url);
37638
37785
  }
37639
37786
  /**
37640
37787
  * 0.4.0+: read declared IndexedDB keys from the user's signed-in
@@ -37681,12 +37828,8 @@ var FetchproxyServer = class {
37681
37828
  const pending = new Promise((resolve, reject) => {
37682
37829
  this.pendingIdb.set(id, { resolve, reject });
37683
37830
  });
37684
- if (this.hostHandle) {
37685
- await this.hostHandle.sendOwnInner(inner);
37686
- } else if (this.peerHandle) {
37687
- await this.peerHandle.sendInner(inner);
37688
- }
37689
- return pending;
37831
+ await this.sendInnerFrame(inner);
37832
+ return this._withVerbTimeout(pending, this.pendingIdb, id, origin);
37690
37833
  }
37691
37834
  assertScopeSubset(requested, declared, label) {
37692
37835
  const undeclared = undeclaredKeys(requested, declared);
@@ -38154,7 +38297,7 @@ function loadAccount(env = process.env) {
38154
38297
  // package.json
38155
38298
  var package_default = {
38156
38299
  name: "signupgenius-mcp",
38157
- version: "1.1.3",
38300
+ version: "1.1.5",
38158
38301
  mcpName: "io.github.chrischall/signupgenius-mcp",
38159
38302
  description: "SignUpGenius MCP server \u2014 read sign-ups, reports, and groups; add group members.",
38160
38303
  author: "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -38191,7 +38334,7 @@ var package_default = {
38191
38334
  "test:watch": "vitest"
38192
38335
  },
38193
38336
  dependencies: {
38194
- "@chrischall/mcp-utils": "^0.8.0",
38337
+ "@chrischall/mcp-utils": "^0.10.4",
38195
38338
  "@fetchproxy/bootstrap": "^1.0.0",
38196
38339
  "@fetchproxy/server": "^1.0.0",
38197
38340
  "@modelcontextprotocol/sdk": "^1.29.0",
@@ -38199,7 +38342,7 @@ var package_default = {
38199
38342
  zod: "^4.4.3"
38200
38343
  },
38201
38344
  devDependencies: {
38202
- "@types/node": "^25.9.1",
38345
+ "@types/node": "^26.0.0",
38203
38346
  "@vitest/coverage-v8": "^4.1.7",
38204
38347
  esbuild: "^0.28.0",
38205
38348
  typescript: "^6.0.3",
@@ -38296,7 +38439,7 @@ var CookieSessionManager = class {
38296
38439
  isPermanentErrorFn;
38297
38440
  constructor(opts) {
38298
38441
  this.loginFn = opts.login;
38299
- this.isExpiredFn = opts.isExpired;
38442
+ this.isExpiredFn = opts.isExpired ?? (() => false);
38300
38443
  this.isPermanentErrorFn = opts.isPermanentError ?? (() => false);
38301
38444
  }
38302
38445
  /** The current session, or `undefined` before the first successful login. */
@@ -38366,6 +38509,10 @@ var CookieSessionManager = class {
38366
38509
  * rather than looping. If the re-login itself fails, the original
38367
38510
  * (expired-looking) response is returned so the caller can surface a clean
38368
38511
  * sign-in error rather than the login failure.
38512
+ *
38513
+ * `call` resolves to `R` (the generic response type, default {@link Response});
38514
+ * the manager passes it untouched to {@link CookieSessionManagerOptions.isExpired}
38515
+ * and returns it untouched, so a custom transport type flows through cleanly.
38369
38516
  */
38370
38517
  async withSession(call) {
38371
38518
  const session = await this.ensure();
@@ -39195,7 +39342,7 @@ bannerLines.push(
39195
39342
  );
39196
39343
  await runMcp({
39197
39344
  name: "signupgenius",
39198
- version: "1.1.3",
39345
+ version: "1.1.5",
39199
39346
  // x-release-please-version
39200
39347
  banner: bannerLines.join("\n"),
39201
39348
  deps: client,
package/dist/index.js CHANGED
@@ -47,7 +47,7 @@ const bannerLines = account
47
47
  bannerLines.push('[signupgenius-mcp] Developed and maintained by AI (Claude). Use at your own discretion.');
48
48
  await runMcp({
49
49
  name: 'signupgenius',
50
- version: '1.1.3', // x-release-please-version
50
+ version: '1.1.5', // x-release-please-version
51
51
  banner: bannerLines.join('\n'),
52
52
  deps: client,
53
53
  tools: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signupgenius-mcp",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
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,7 @@
37
37
  "test:watch": "vitest"
38
38
  },
39
39
  "dependencies": {
40
- "@chrischall/mcp-utils": "^0.8.0",
40
+ "@chrischall/mcp-utils": "^0.10.4",
41
41
  "@fetchproxy/bootstrap": "^1.0.0",
42
42
  "@fetchproxy/server": "^1.0.0",
43
43
  "@modelcontextprotocol/sdk": "^1.29.0",
@@ -45,7 +45,7 @@
45
45
  "zod": "^4.4.3"
46
46
  },
47
47
  "devDependencies": {
48
- "@types/node": "^25.9.1",
48
+ "@types/node": "^26.0.0",
49
49
  "@vitest/coverage-v8": "^4.1.7",
50
50
  "esbuild": "^0.28.0",
51
51
  "typescript": "^6.0.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.1.3",
9
+ "version": "1.1.5",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "signupgenius-mcp",
14
- "version": "1.1.3",
14
+ "version": "1.1.5",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },