honeybook-mcp 1.2.3 → 1.2.4

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": "HoneyBook client-portal tools for Claude Code",
10
- "version": "1.2.3"
10
+ "version": "1.2.4"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "HoneyBook",
16
16
  "source": "./",
17
17
  "description": "HoneyBook client-portal MCP for Claude — view wedding-vendor contracts and invoices via MCP",
18
- "version": "1.2.3",
18
+ "version": "1.2.4",
19
19
  "author": {
20
20
  "name": "Chris Chall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "honeybook",
3
3
  "displayName": "HoneyBook",
4
- "version": "1.2.3",
4
+ "version": "1.2.4",
5
5
  "description": "HoneyBook client-portal MCP for Claude — view wedding-vendor contracts and invoices via MCP",
6
6
  "author": {
7
7
  "name": "Chris Chall",
package/dist/bundle.js CHANGED
@@ -20692,8 +20692,8 @@ var require_schemas2 = __commonJS({
20692
20692
  return core._stringFormat(exports.ZodCustomStringFormat, "currency_code", regexes.currencyCode, _params);
20693
20693
  }
20694
20694
  function hash2(alg, params) {
20695
- const enc6 = params?.enc ?? "hex";
20696
- const format = `${alg}_${enc6}`;
20695
+ const enc7 = params?.enc ?? "hex";
20696
+ const format = `${alg}_${enc7}`;
20697
20697
  const regex = core.regexes[format];
20698
20698
  if (!regex)
20699
20699
  throw new Error(`Unrecognized hash format: ${format}`);
@@ -28038,7 +28038,7 @@ var OAuthTokenRevocationRequestSchema = z.object({
28038
28038
  token_type_hint: z.string().optional()
28039
28039
  }).strip();
28040
28040
 
28041
- // node_modules/@modelcontextprotocol/server/dist/src-BHSMhZ_W.mjs
28041
+ // node_modules/@modelcontextprotocol/server/dist/src-Cqbh3MYc.mjs
28042
28042
  var z2 = __toESM(require_v4(), 1);
28043
28043
  var BRANDS = /* @__PURE__ */ Symbol.for("mcp.sdk.errorBrands");
28044
28044
  function stampErrorBrands(instance, ctor) {
@@ -30282,7 +30282,8 @@ function build() {
30282
30282
  ListResourceTemplatesResultResponseSchema: wireResultResponse(ListResourceTemplatesResultSchema$1),
30283
30283
  ReadResourceResultResponseSchema: wireResultResponse(z2.union([ReadResourceResultSchema$1, InputRequiredResultSchema])),
30284
30284
  CompleteResultResponseSchema: wireResultResponse(CompleteResultSchema$1),
30285
- DiscoverResultResponseSchema: wireResultResponse(DiscoverResultSchema$1)
30285
+ DiscoverResultResponseSchema: wireResultResponse(DiscoverResultSchema$1),
30286
+ SubscriptionsListenResultResponseSchema: wireResultResponse(SubscriptionsListenResultSchema$1)
30286
30287
  };
30287
30288
  }
30288
30289
  var memo;
@@ -30790,6 +30791,9 @@ function isSpecRequestMethod(method) {
30790
30791
  function isSpecNotificationMethod(method) {
30791
30792
  return ALL_CODECS.some((codec2) => codec2.hasNotificationMethod(method));
30792
30793
  }
30794
+ function isExtensionReusedRequestMethod(method) {
30795
+ return method === "tasks/get" || method === "tasks/cancel";
30796
+ }
30793
30797
  var ALL_CODECS = [rev2025Codec, rev2026Codec];
30794
30798
  function isPlainObject$3(value) {
30795
30799
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -31798,6 +31802,8 @@ var Protocol = class {
31798
31802
  _transport;
31799
31803
  _requestMessageId = 0;
31800
31804
  _requestHandlers = /* @__PURE__ */ new Map();
31805
+ /** Methods registered with an explicit schema; the era gate in `_onrequest` reads it for the Tasks extension names. */
31806
+ _customSchemaRequestMethods = /* @__PURE__ */ new Set();
31801
31807
  _requestHandlerAbortControllers = /* @__PURE__ */ new Map();
31802
31808
  _notificationHandlers = /* @__PURE__ */ new Map();
31803
31809
  _responseHandlers = /* @__PURE__ */ new Map();
@@ -32081,7 +32087,7 @@ var Protocol = class {
32081
32087
  return;
32082
32088
  }
32083
32089
  }
32084
- if (isSpecRequestMethod(request.method) && !codec2.hasRequestMethod(request.method)) {
32090
+ if (isSpecRequestMethod(request.method) && !codec2.hasRequestMethod(request.method) && !(isExtensionReusedRequestMethod(request.method) && this._customSchemaRequestMethods.has(request.method))) {
32085
32091
  sendErrorResponse(ProtocolErrorCode.MethodNotFound, "Method not found");
32086
32092
  return;
32087
32093
  }
@@ -32214,8 +32220,11 @@ var Protocol = class {
32214
32220
  }
32215
32221
  request(request, schemaOrOptions, maybeOptions) {
32216
32222
  const codec2 = this._resolveOutboundCodec(request.method);
32223
+ if (isStandardSchema(schemaOrOptions)) {
32224
+ if (!isExtensionReusedRequestMethod(request.method)) this._assertOutboundRequestInEra(codec2, request.method);
32225
+ return this._requestWithSchemaViaCodec(codec2, request, schemaOrOptions, maybeOptions);
32226
+ }
32217
32227
  this._assertOutboundRequestInEra(codec2, request.method);
32218
- if (isStandardSchema(schemaOrOptions)) return this._requestWithSchemaViaCodec(codec2, request, schemaOrOptions, maybeOptions);
32219
32228
  const validate2 = codecResultValidator(codec2, request.method);
32220
32229
  if (validate2 === void 0) throw new TypeError(`'${request.method}' is not a spec method; pass a result schema as the second argument to request().`);
32221
32230
  return this._requestWithSchemaViaCodec(codec2, request, validate2, schemaOrOptions);
@@ -32459,6 +32468,8 @@ var Protocol = class {
32459
32468
  return maybeHandler(parsed.data, ctx);
32460
32469
  };
32461
32470
  else throw new TypeError("setRequestHandler: handler is required");
32471
+ if (typeof schemasOrHandler === "function") this._customSchemaRequestMethods.delete(method);
32472
+ else this._customSchemaRequestMethods.add(method);
32462
32473
  this._requestHandlers.set(method, this._wrapHandler(method, stored));
32463
32474
  }
32464
32475
  /**
@@ -32488,6 +32499,7 @@ var Protocol = class {
32488
32499
  */
32489
32500
  removeRequestHandler(method) {
32490
32501
  this._requestHandlers.delete(method);
32502
+ this._customSchemaRequestMethods.delete(method);
32491
32503
  }
32492
32504
  /**
32493
32505
  * Asserts that a request handler has not already been set for the given method, in preparation for a new one being automatically installed.
@@ -39730,7 +39742,7 @@ var Ajv = import_ajv.Ajv;
39730
39742
  // node_modules/@modelcontextprotocol/server/dist/shimsNode.mjs
39731
39743
  import process2 from "node:process";
39732
39744
 
39733
- // node_modules/@modelcontextprotocol/server/dist/mcp-DYuW2ZSs.mjs
39745
+ // node_modules/@modelcontextprotocol/server/dist/mcp-DIH4cS6P.mjs
39734
39746
  var COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
39735
39747
  function isCompletable(schema) {
39736
39748
  return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
@@ -39795,7 +39807,7 @@ var StdioListenRouter = class {
39795
39807
  _serverCapabilities;
39796
39808
  /**
39797
39809
  * The serving instance's identity, stamped onto the graceful-close
39798
- * results' `_meta` (the spec's `SubscriptionsListenResultMeta` extends
39810
+ * results' `_meta` (the spec's `SubscriptionsListenResultMetaObject` extends
39799
39811
  * `ResultMetaObject`). Handed over together with the capabilities.
39800
39812
  */
39801
39813
  _serverInfo;
@@ -40127,6 +40139,11 @@ var Server = class extends Protocol {
40127
40139
  if (modernProtocolVersions(this._supportedProtocolVersions).length > 0) this.setRequestHandler("server/discover", () => this._ondiscover());
40128
40140
  if (this._capabilities.logging) this._registerLoggingHandler();
40129
40141
  }
40142
+ /** Attaches to the given transport; rejects while this instance is connected to another one. */
40143
+ async connect(transport) {
40144
+ if (this.transport !== void 0) throw new SdkError(SdkErrorCode.AlreadyConnected, "Use a separate Server instance per connection: this instance is already connected to a transport. To connect it to a new transport, call close() first.");
40145
+ await super.connect(transport);
40146
+ }
40130
40147
  /**
40131
40148
  * Registers the built-in `logging/setLevel` request handler.
40132
40149
  *
@@ -40680,21 +40697,41 @@ var Server = class extends Protocol {
40680
40697
  function discoverAdvertisedCapabilities(capabilities) {
40681
40698
  return { ...capabilities };
40682
40699
  }
40700
+ function toolInputElementCount(value, max) {
40701
+ let count = 0;
40702
+ const stack = [value];
40703
+ while (stack.length > 0) {
40704
+ const node2 = stack.pop();
40705
+ if (node2 === null || typeof node2 !== "object") continue;
40706
+ if (Array.isArray(node2)) for (const child of node2) {
40707
+ if (++count > max) return count;
40708
+ if (child !== null && typeof child === "object") stack.push(child);
40709
+ }
40710
+ else for (const key in node2) {
40711
+ if (!Object.prototype.hasOwnProperty.call(node2, key)) continue;
40712
+ if (++count > max) return count;
40713
+ const child = node2[key];
40714
+ if (child !== null && typeof child === "object") stack.push(child);
40715
+ }
40716
+ }
40717
+ return count;
40718
+ }
40719
+ function resolveMaxToolInputElements(value) {
40720
+ if (value === void 0 || value === Infinity) return void 0;
40721
+ if (typeof value !== "number" || Number.isNaN(value) || value < 1) throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`);
40722
+ return value;
40723
+ }
40683
40724
  var McpServer = class {
40684
40725
  /**
40685
40726
  * The underlying {@linkcode Server} instance, useful for advanced operations like sending notifications.
40686
40727
  */
40687
40728
  server;
40729
+ _maxToolInputElements;
40688
40730
  _registeredResources = {};
40689
40731
  _registeredResourceTemplates = {};
40690
40732
  _registeredTools = {};
40691
40733
  _registeredPrompts = {};
40692
- /**
40693
- * Per-tool JSON-converted `inputSchema`, memoized so the SEP-2243
40694
- * registration-time scan and the pre-dispatch validation step share one
40695
- * conversion instead of paying it twice per request under the
40696
- * per-request-factory `createMcpHandler` model.
40697
- */
40734
+ /** Per-tool JSON-converted `inputSchema`, filled on first use by `toolInputSchemaJson()`. */
40698
40735
  _toolInputSchemaJson = {};
40699
40736
  /**
40700
40737
  * The JSON-serialized `inputSchema` of a registered tool, or `undefined`
@@ -40719,6 +40756,7 @@ var McpServer = class {
40719
40756
  }
40720
40757
  constructor(serverInfo, options) {
40721
40758
  this.server = new Server(serverInfo, options);
40759
+ this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
40722
40760
  if (options?.capabilities?.tools) this.setToolRequestHandlers();
40723
40761
  if (options?.capabilities?.resources) this.setResourceRequestHandlers();
40724
40762
  if (options?.capabilities?.prompts) this.setPromptRequestHandlers();
@@ -40791,7 +40829,7 @@ var McpServer = class {
40791
40829
  name,
40792
40830
  title: tool.title,
40793
40831
  description: tool.description,
40794
- inputSchema: tool.inputSchema ? standardSchemaToJsonSchema(tool.inputSchema, "input") : EMPTY_OBJECT_JSON_SCHEMA,
40832
+ inputSchema: tool.inputSchema ? convertListedInputSchema(name, tool.inputSchema) : EMPTY_OBJECT_JSON_SCHEMA,
40795
40833
  annotations: tool.annotations,
40796
40834
  icons: tool.icons,
40797
40835
  execution: tool.execution,
@@ -40836,6 +40874,7 @@ var McpServer = class {
40836
40874
  * Validates tool input arguments against the tool's input schema.
40837
40875
  */
40838
40876
  async validateToolInput(tool, args, toolName) {
40877
+ if (this._maxToolInputElements !== void 0 && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
40839
40878
  if (!tool.inputSchema) return;
40840
40879
  const parseResult = await validateStandardSchema(tool.inputSchema, args ?? {});
40841
40880
  if (!parseResult.success) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${parseResult.error}`);
@@ -41110,20 +41149,19 @@ var McpServer = class {
41110
41149
  }
41111
41150
  _createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, icons, execution, scopeChallenge, _meta, handler) {
41112
41151
  validateAndWarnToolName(name);
41113
- if (inputSchema !== void 0) try {
41114
- const json2 = standardSchemaToJsonSchema(inputSchema, "input");
41115
- this._toolInputSchemaJson[name] = json2;
41116
- const scan = scanXMcpHeaderDeclarations(json2);
41117
- if (!scan.valid) console.warn(`[mcp-sdk] tool '${name}' carries an invalid x-mcp-header declaration and will be excluded by conforming Streamable HTTP clients: ${scan.reason}`);
41118
- } catch {
41119
- }
41120
41152
  let currentHandler = handler;
41153
+ let outputSchemaJson;
41121
41154
  const registeredTool = {
41122
41155
  title,
41123
41156
  description,
41124
41157
  inputSchema,
41125
41158
  outputSchema,
41126
- outputSchemaJson: convertOutputSchemaJson(outputSchema),
41159
+ get outputSchemaJson() {
41160
+ return outputSchemaJson ??= convertOutputSchemaJson(registeredTool.outputSchema);
41161
+ },
41162
+ set outputSchemaJson(value) {
41163
+ outputSchemaJson = value;
41164
+ },
41127
41165
  annotations,
41128
41166
  icons,
41129
41167
  execution,
@@ -41250,6 +41288,12 @@ var EMPTY_OBJECT_JSON_SCHEMA = {
41250
41288
  type: "object",
41251
41289
  properties: {}
41252
41290
  };
41291
+ function convertListedInputSchema(name, inputSchema) {
41292
+ const json2 = standardSchemaToJsonSchema(inputSchema, "input");
41293
+ const scan = scanXMcpHeaderDeclarations(json2);
41294
+ if (!scan.valid) console.warn(`[mcp-sdk] tool '${name}' carries an invalid x-mcp-header declaration and will be excluded by conforming Streamable HTTP clients: ${scan.reason}`);
41295
+ return json2;
41296
+ }
41253
41297
  function convertOutputSchemaJson(outputSchema) {
41254
41298
  if (outputSchema === void 0) return void 0;
41255
41299
  try {
@@ -41262,7 +41306,7 @@ function createPromptHandler(name, argsSchema, callback) {
41262
41306
  if (argsSchema) {
41263
41307
  const typedCallback = callback;
41264
41308
  return async (args, ctx) => {
41265
- const parseResult = await validateStandardSchema(argsSchema, args);
41309
+ const parseResult = await validateStandardSchema(argsSchema, args ?? {});
41266
41310
  if (!parseResult.success) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid arguments for prompt ${name}: ${parseResult.error}`);
41267
41311
  return typedCallback(parseResult.data, ctx);
41268
41312
  };
@@ -59619,8 +59663,8 @@ function currencyCode2(_params) {
59619
59663
  return _stringFormat(ZodCustomStringFormat, "currency_code", currencyCode, _params);
59620
59664
  }
59621
59665
  function hash(alg, params) {
59622
- const enc6 = params?.enc ?? "hex";
59623
- const format = `${alg}_${enc6}`;
59666
+ const enc7 = params?.enc ?? "hex";
59667
+ const format = `${alg}_${enc7}`;
59624
59668
  const regex = regexes_exports[format];
59625
59669
  if (!regex)
59626
59670
  throw new Error(`Unrecognized hash format: ${format}`);
@@ -62243,7 +62287,10 @@ function surfaceToolHints(server) {
62243
62287
  ));
62244
62288
  }
62245
62289
  async function createMcpServer(opts) {
62246
- const server = new McpServer({ name: opts.name, version: opts.version }, { supportedProtocolVersions: [...SERVER_PROTOCOL_VERSIONS] });
62290
+ const server = new McpServer({ name: opts.name, version: opts.version }, {
62291
+ supportedProtocolVersions: [...SERVER_PROTOCOL_VERSIONS],
62292
+ ...opts.maxToolInputElements !== void 0 ? { maxToolInputElements: opts.maxToolInputElements } : {}
62293
+ });
62247
62294
  if (opts.surfaceHints !== false)
62248
62295
  surfaceToolHints(server);
62249
62296
  if (opts.banner !== void 0) {
@@ -63313,6 +63360,49 @@ var KNOWN_CAPABILITIES = /* @__PURE__ */ new Set([
63313
63360
  "graphql",
63314
63361
  "write_cookies"
63315
63362
  ]);
63363
+ var ACCOUNT_KEY_FRAME = "account-key";
63364
+ var ACCOUNT_ATTEST_FRAME = "account-attest";
63365
+
63366
+ // node_modules/@fetchproxy/protocol/dist/mcp-id.js
63367
+ var ID_RE = /^([^:]+):([^:]+):([0-9a-f]{16})$/;
63368
+ function generateMcpId(serverName, version2) {
63369
+ if (serverName.includes(":")) {
63370
+ throw new Error(`serverName cannot contain ':': ${serverName}`);
63371
+ }
63372
+ if (version2.includes(":")) {
63373
+ throw new Error(`version cannot contain ':': ${version2}`);
63374
+ }
63375
+ const rand = randomHex(8);
63376
+ return `${serverName}:${version2}:${rand}`;
63377
+ }
63378
+ function isValidMcpId(id) {
63379
+ return typeof id === "string" && ID_RE.test(id);
63380
+ }
63381
+ function randomHex(bytes) {
63382
+ const arr2 = new Uint8Array(bytes);
63383
+ globalThis.crypto.getRandomValues(arr2);
63384
+ return Array.from(arr2, (b) => b.toString(16).padStart(2, "0")).join("");
63385
+ }
63386
+
63387
+ // node_modules/@fetchproxy/protocol/dist/account-attest.js
63388
+ var ACCOUNT_ATTEST_CONSENTS = Object.freeze([
63389
+ "silent",
63390
+ "confirm",
63391
+ "confirm-each"
63392
+ ]);
63393
+ var NO_SCOPE_DIGEST = "0".repeat(64);
63394
+ var ACCOUNT_ID_RE = /^[A-Za-z0-9_.\-]{1,128}$/;
63395
+ var HEX64_RE = /^[0-9a-f]{64}$/;
63396
+ var ACCOUNT_KID_RE = /^[0-9a-f]{16}$/;
63397
+ var enc2 = new TextEncoder();
63398
+
63399
+ // node_modules/@fetchproxy/protocol/dist/awaiting-approval.js
63400
+ var AWAITING_APPROVAL_REASON_PREFIX = "awaiting-approval:";
63401
+ function parseAwaitingApprovalReason(reason) {
63402
+ if (!reason.startsWith(AWAITING_APPROVAL_REASON_PREFIX))
63403
+ return null;
63404
+ return reason.slice(AWAITING_APPROVAL_REASON_PREFIX.length).trim();
63405
+ }
63316
63406
 
63317
63407
  // node_modules/@fetchproxy/protocol/dist/capability-availability.js
63318
63408
  var CAPABILITY_UNAVAILABLE_CODE = "capability_unavailable";
@@ -63338,27 +63428,6 @@ function parseUnsupportedCapabilityReason(reason) {
63338
63428
  return rest.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
63339
63429
  }
63340
63430
 
63341
- // node_modules/@fetchproxy/protocol/dist/mcp-id.js
63342
- var ID_RE = /^([^:]+):([^:]+):([0-9a-f]{16})$/;
63343
- function generateMcpId(serverName, version2) {
63344
- if (serverName.includes(":")) {
63345
- throw new Error(`serverName cannot contain ':': ${serverName}`);
63346
- }
63347
- if (version2.includes(":")) {
63348
- throw new Error(`version cannot contain ':': ${version2}`);
63349
- }
63350
- const rand = randomHex(8);
63351
- return `${serverName}:${version2}:${rand}`;
63352
- }
63353
- function isValidMcpId(id) {
63354
- return typeof id === "string" && ID_RE.test(id);
63355
- }
63356
- function randomHex(bytes) {
63357
- const arr2 = new Uint8Array(bytes);
63358
- globalThis.crypto.getRandomValues(arr2);
63359
- return Array.from(arr2, (b) => b.toString(16).padStart(2, "0")).join("");
63360
- }
63361
-
63362
63431
  // node_modules/@fetchproxy/protocol/dist/json-pointer.js
63363
63432
  function matchesDeclaredKey(requested, declared) {
63364
63433
  for (const decl of declared) {
@@ -63954,6 +64023,10 @@ function validateFrame(raw) {
63954
64023
  return { type: "extension-disconnected" };
63955
64024
  if (t === "peer-gone")
63956
64025
  return validatePeerGone(raw);
64026
+ if (t === ACCOUNT_KEY_FRAME)
64027
+ return validateAccountKey(raw);
64028
+ if (t === ACCOUNT_ATTEST_FRAME)
64029
+ return validateAccountAttest(raw);
63957
64030
  throw new ProtocolError3(`unknown frame type: ${String(t)}`);
63958
64031
  }
63959
64032
  function validateHello(raw) {
@@ -64157,6 +64230,128 @@ function validateHelloRejected(raw) {
64157
64230
  }
64158
64231
  return { type: "hello-rejected", mcpId: raw.mcpId, reason: raw.reason };
64159
64232
  }
64233
+ var DISPLAY_FORBIDDEN_RE = /[\u0000-\u001f\u007f-\u009f\u200e\u200f\u202a-\u202e\u2066-\u2069]/;
64234
+ function assertExactFields(raw, allowed, label) {
64235
+ for (const k of Object.keys(raw)) {
64236
+ if (!allowed.includes(k)) {
64237
+ throw new ProtocolError3(`${label}: unexpected field ${JSON.stringify(k)}`);
64238
+ }
64239
+ }
64240
+ }
64241
+ function assertMatch(x, re, label, what) {
64242
+ assertString(x, label);
64243
+ if (!re.test(x))
64244
+ throw new ProtocolError3(`${label}: must be ${what}`);
64245
+ }
64246
+ function assertPositiveSafeInt(x, label) {
64247
+ if (typeof x !== "number" || !Number.isSafeInteger(x) || x <= 0) {
64248
+ throw new ProtocolError3(`${label}: expected positive safe integer`);
64249
+ }
64250
+ }
64251
+ function assertDisplayString(x, label, min, max) {
64252
+ assertString(x, label);
64253
+ if (x.length < min || x.length > max) {
64254
+ throw new ProtocolError3(`${label}: must be ${min}-${max} characters`);
64255
+ }
64256
+ if (DISPLAY_FORBIDDEN_RE.test(x)) {
64257
+ throw new ProtocolError3(`${label}: control or bidi-override character`);
64258
+ }
64259
+ }
64260
+ var ACCOUNT_KEY_FIELDS = [
64261
+ "type",
64262
+ "accountId",
64263
+ "slug",
64264
+ "displayName",
64265
+ "confirmedBy",
64266
+ "tokenId",
64267
+ "kid",
64268
+ "publicKey",
64269
+ "generation",
64270
+ "bridgedRegistrations"
64271
+ ];
64272
+ function validateAccountKey(raw) {
64273
+ const L = "account-key";
64274
+ assertMatch(raw.accountId, ACCOUNT_ID_RE, `${L}.accountId`, "an account id");
64275
+ assertMatch(raw.slug, ACCOUNT_ID_RE, `${L}.slug`, "a slug");
64276
+ assertDisplayString(raw.displayName, `${L}.displayName`, 0, 128);
64277
+ assertDisplayString(raw.confirmedBy, `${L}.confirmedBy`, 1, 256);
64278
+ assertMatch(raw.tokenId, ACCOUNT_ID_RE, `${L}.tokenId`, "a token id");
64279
+ assertMatch(raw.kid, ACCOUNT_KID_RE, `${L}.kid`, "16 lowercase hex");
64280
+ assertBase64Bytes(raw.publicKey, `${L}.publicKey`, 32);
64281
+ assertPositiveSafeInt(raw.generation, `${L}.generation`);
64282
+ const n = raw.bridgedRegistrations;
64283
+ if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 0) {
64284
+ throw new ProtocolError3(`${L}.bridgedRegistrations: expected non-negative safe integer`);
64285
+ }
64286
+ assertExactFields(raw, ACCOUNT_KEY_FIELDS, L);
64287
+ return {
64288
+ type: ACCOUNT_KEY_FRAME,
64289
+ accountId: raw.accountId,
64290
+ slug: raw.slug,
64291
+ displayName: raw.displayName,
64292
+ confirmedBy: raw.confirmedBy,
64293
+ tokenId: raw.tokenId,
64294
+ kid: raw.kid,
64295
+ publicKey: raw.publicKey,
64296
+ generation: raw.generation,
64297
+ bridgedRegistrations: n
64298
+ };
64299
+ }
64300
+ var ACCOUNT_ATTEST_FIELDS = [
64301
+ "type",
64302
+ "mcpId",
64303
+ "accountId",
64304
+ "generation",
64305
+ "tokenId",
64306
+ "kid",
64307
+ "registrationId",
64308
+ "slug",
64309
+ "identityHash",
64310
+ "identityEd25519Pub",
64311
+ "scopeDigest",
64312
+ "consent",
64313
+ "notAfter",
64314
+ "sig"
64315
+ ];
64316
+ function validateAccountAttest(raw) {
64317
+ const L = "account-attest";
64318
+ if (!isValidMcpId(raw.mcpId))
64319
+ throw new ProtocolError3(`${L}.mcpId: invalid format`);
64320
+ assertMatch(raw.accountId, ACCOUNT_ID_RE, `${L}.accountId`, "an account id");
64321
+ assertPositiveSafeInt(raw.generation, `${L}.generation`);
64322
+ assertMatch(raw.tokenId, ACCOUNT_ID_RE, `${L}.tokenId`, "a token id");
64323
+ assertMatch(raw.kid, ACCOUNT_KID_RE, `${L}.kid`, "16 lowercase hex");
64324
+ assertMatch(raw.registrationId, ACCOUNT_ID_RE, `${L}.registrationId`, "a registration id");
64325
+ assertMatch(raw.slug, ACCOUNT_ID_RE, `${L}.slug`, "a slug");
64326
+ assertMatch(raw.identityHash, HEX64_RE, `${L}.identityHash`, "64 lowercase hex");
64327
+ assertBase64Bytes(raw.identityEd25519Pub, `${L}.identityEd25519Pub`, 32);
64328
+ assertMatch(raw.scopeDigest, HEX64_RE, `${L}.scopeDigest`, "64 lowercase hex");
64329
+ assertString(raw.consent, `${L}.consent`);
64330
+ const consent = raw.consent;
64331
+ const known = ACCOUNT_ATTEST_CONSENTS.find((c) => c === consent);
64332
+ if (known === void 0) {
64333
+ throw new ProtocolError3(`${L}.consent: must be one of ${ACCOUNT_ATTEST_CONSENTS.join(", ")}`);
64334
+ }
64335
+ assertPositiveSafeInt(raw.notAfter, `${L}.notAfter`);
64336
+ assertBase64Bytes(raw.sig, `${L}.sig`, 64);
64337
+ assertExactFields(raw, ACCOUNT_ATTEST_FIELDS, L);
64338
+ return {
64339
+ type: ACCOUNT_ATTEST_FRAME,
64340
+ mcpId: raw.mcpId,
64341
+ accountId: raw.accountId,
64342
+ generation: raw.generation,
64343
+ tokenId: raw.tokenId,
64344
+ kid: raw.kid,
64345
+ registrationId: raw.registrationId,
64346
+ slug: raw.slug,
64347
+ identityHash: raw.identityHash,
64348
+ identityEd25519Pub: raw.identityEd25519Pub,
64349
+ scopeDigest: raw.scopeDigest,
64350
+ consent: known,
64351
+ notAfter: raw.notAfter,
64352
+ sig: raw.sig
64353
+ };
64354
+ }
64160
64355
  function validateInnerFrame(raw) {
64161
64356
  assertObject(raw, "inner");
64162
64357
  const t = raw.type;
@@ -64624,10 +64819,10 @@ function validateInnerResponse(raw) {
64624
64819
  }
64625
64820
 
64626
64821
  // node_modules/@fetchproxy/protocol/dist/pair-code.js
64627
- var enc2 = new TextEncoder();
64822
+ var enc3 = new TextEncoder();
64628
64823
  var PAIR_LABEL = "fetchproxy/4/pair";
64629
64824
  async function pairTranscript(mcpIdentityPub, extIdentityPub, mcpNonce, extNonce, mcpSessionPub) {
64630
- const label = enc2.encode(PAIR_LABEL);
64825
+ const label = enc3.encode(PAIR_LABEL);
64631
64826
  const parts = [mcpIdentityPub, extIdentityPub, mcpNonce, extNonce, mcpSessionPub];
64632
64827
  const out = new Uint8Array(label.length + 1 + parts.reduce((n, p) => n + p.length, 0));
64633
64828
  out.set(label, 0);
@@ -64648,7 +64843,7 @@ function digits(hash2) {
64648
64843
  }
64649
64844
 
64650
64845
  // node_modules/@fetchproxy/protocol/dist/seal.js
64651
- var enc3 = new TextEncoder();
64846
+ var enc4 = new TextEncoder();
64652
64847
  var dec = new TextDecoder();
64653
64848
  function randomIv() {
64654
64849
  const iv = new Uint8Array(12);
@@ -64661,14 +64856,14 @@ function base64Length(byteLength) {
64661
64856
  return Math.ceil(byteLength / 3) * 4;
64662
64857
  }
64663
64858
  function encodeInnerFrame(inner) {
64664
- return enc3.encode(JSON.stringify(inner));
64859
+ return enc4.encode(JSON.stringify(inner));
64665
64860
  }
64666
64861
  function plaintextOf(inner) {
64667
64862
  return inner instanceof Uint8Array ? inner : encodeInnerFrame(inner);
64668
64863
  }
64669
64864
  function sealedFrameWireBytes(mcpId, seq, inner) {
64670
64865
  const plaintext = plaintextOf(inner).length;
64671
- const envelope = enc3.encode(JSON.stringify({ type: "frame", mcpId, seq, iv: "", ciphertext: "" })).length;
64866
+ const envelope = enc4.encode(JSON.stringify({ type: "frame", mcpId, seq, iv: "", ciphertext: "" })).length;
64672
64867
  return envelope + IV_B64_BYTES + base64Length(plaintext + AES_GCM_TAG_BYTES);
64673
64868
  }
64674
64869
  var MAX_FRAME_BYTES = 42 * 1024 * 1024;
@@ -65008,14 +65203,23 @@ var FetchproxyHelloRejectedError = class extends Error {
65008
65203
  platform;
65009
65204
  /**
65010
65205
  * #418: the remedy, when the reason is one this package knows how to
65011
- * explain — today only `unsupported-capability`, which blames the browser
65012
- * rather than the MCP. `null` otherwise.
65206
+ * explain — `unsupported-capability`, which blames the browser rather than
65207
+ * the MCP, and (D12) `awaiting-approval`, which says to approve in the
65208
+ * browser. `null` otherwise.
65013
65209
  */
65014
65210
  hint;
65211
+ /**
65212
+ * D12: `true` only for an `awaiting-approval:` refusal — the extension has
65213
+ * queued an approval card and nobody is at the browser yet, so the same call
65214
+ * succeeds once the person approves. Every other refusal is the extension's
65215
+ * final answer, and retrying unchanged is refused the same way.
65216
+ */
65217
+ retryable;
65015
65218
  constructor(info) {
65016
65219
  const unavailable = parseUnsupportedCapabilityReason(info.reason);
65220
+ const awaiting = parseAwaitingApprovalReason(info.reason);
65017
65221
  const platform = info.platform ?? null;
65018
- const hint = unavailable !== null ? `${platform ? `this browser (${platform})` : "this browser"} cannot serve any of the capabilities this MCP needs (${unavailable.join(", ")}) \u2014 ContextMint Bridge checked for the browser APIs and they are missing. Nothing is wrong with the MCP or your pairing, and updating will not change it: use this MCP from a browser that provides them (for example Chrome).` : null;
65222
+ const hint = awaiting !== null ? `The extension is waiting for you to approve this MCP` + (awaiting !== "" ? ` (${awaiting})` : "") + ` \u2014 open ContextMint Bridge in your browser, approve it there, then retry. Nothing is wrong with the MCP or your sign-in.` : unavailable !== null ? `${platform ? `this browser (${platform})` : "this browser"} cannot serve any of the capabilities this MCP needs (${unavailable.join(", ")}) \u2014 ContextMint Bridge checked for the browser APIs and they are missing. Nothing is wrong with the MCP or your pairing, and updating will not change it: use this MCP from a browser that provides them (for example Chrome).` : null;
65019
65223
  super(`fetchproxy: the extension refused the connection for "${info.mcpId}": ${info.reason}. ` + (hint !== null ? hint : `This is the extension's own reason \u2014 it is not a timeout, and retrying unchanged will be refused the same way.`));
65020
65224
  this.name = "FetchproxyHelloRejectedError";
65021
65225
  this.mcpId = info.mcpId;
@@ -65023,6 +65227,7 @@ var FetchproxyHelloRejectedError = class extends Error {
65023
65227
  this.unavailableCapabilities = unavailable ?? [];
65024
65228
  this.platform = platform;
65025
65229
  this.hint = hint;
65230
+ this.retryable = awaiting !== null;
65026
65231
  Object.setPrototypeOf(this, new.target.prototype);
65027
65232
  }
65028
65233
  };
@@ -65575,7 +65780,7 @@ function originVerdict(origin, allowLocal) {
65575
65780
  }
65576
65781
  var HANDSHAKE_TIMEOUT_MS = 15e3;
65577
65782
  var MAX_PAYLOAD_BYTES = MAX_FRAME_BYTES;
65578
- var enc4 = new TextEncoder();
65783
+ var enc5 = new TextEncoder();
65579
65784
  var OWN_DECRYPT_FAILURES_BEFORE_REHANDSHAKE = 3;
65580
65785
  async function startHost(opts) {
65581
65786
  const allowLocalOrigins = envAllowsLocalOrigins();
@@ -65646,10 +65851,20 @@ async function startHost(opts) {
65646
65851
  let resolveOwnSession;
65647
65852
  let rejectOwnSession;
65648
65853
  let ownSessionReady;
65854
+ let ownRetryableRefusal = false;
65855
+ let ownSessionSettled = false;
65649
65856
  function resetSessionPromise() {
65857
+ ownRetryableRefusal = false;
65858
+ ownSessionSettled = false;
65650
65859
  ownSessionReady = new Promise((resolve2, reject) => {
65651
- resolveOwnSession = resolve2;
65652
- rejectOwnSession = reject;
65860
+ resolveOwnSession = (st) => {
65861
+ ownSessionSettled = true;
65862
+ resolve2(st);
65863
+ };
65864
+ rejectOwnSession = (e) => {
65865
+ ownSessionSettled = true;
65866
+ reject(e);
65867
+ };
65653
65868
  });
65654
65869
  ownSessionReady.catch(() => {
65655
65870
  });
@@ -65916,13 +66131,15 @@ async function startHost(opts) {
65916
66131
  const extPub = fromB64(frame.extensionSessionPub);
65917
66132
  const shared = await ecdhX25519(held.priv, extPub);
65918
66133
  const salt = await transcriptHash(held.nonce, extNonce, held.pub, extPub);
65919
- const key = await hkdfSha256(shared, salt, enc4.encode(HKDF_SESSION_INFO), 32);
66134
+ const key = await hkdfSha256(shared, salt, enc5.encode(HKDF_SESSION_INFO), 32);
65920
66135
  if (extensionWs !== ws)
65921
66136
  return;
65922
66137
  ownSession = new SessionState(key);
65923
66138
  ownSessionInfo = sessionInfoFromHello(verifiedHello);
65924
66139
  ownDecryptFailures = 0;
65925
66140
  ownPendingPairCode = null;
66141
+ if (ownRetryableRefusal)
66142
+ resetSessionPromise();
65926
66143
  resolveOwnSession(ownSession);
65927
66144
  } else {
65928
66145
  const slot = peers.get(frame.mcpId);
@@ -65991,11 +66208,17 @@ async function startHost(opts) {
65991
66208
  }
65992
66209
  if (frame.type === "hello-rejected" && identified === "extension") {
65993
66210
  if (frame.mcpId === opts.ownMcpId) {
65994
- rejectOwnSession(new FetchproxyHelloRejectedError({
66211
+ const refusal = new FetchproxyHelloRejectedError({
65995
66212
  mcpId: frame.mcpId,
65996
66213
  reason: frame.reason,
65997
66214
  platform: extensionHello?.platform ?? null
65998
- }));
66215
+ });
66216
+ if (ownRetryableRefusal)
66217
+ resetSessionPromise();
66218
+ const settlesPending = !ownSessionSettled;
66219
+ rejectOwnSession(refusal);
66220
+ if (refusal.retryable && settlesPending)
66221
+ ownRetryableRefusal = true;
65999
66222
  } else {
66000
66223
  const slot = peers.get(frame.mcpId);
66001
66224
  if (slot?.helloFrame.accepts?.includes("hello-rejected")) {
@@ -66111,7 +66334,7 @@ async function startHost(opts) {
66111
66334
 
66112
66335
  // node_modules/@fetchproxy/server/dist/peer.js
66113
66336
  var PEER_DIAL_TIMEOUT_MS = 5e3;
66114
- var enc5 = new TextEncoder();
66337
+ var enc6 = new TextEncoder();
66115
66338
  function notSentError() {
66116
66339
  return new Error("fetchproxy: request not sent \u2014 the connection to the bridge host closed before it went out, so nothing reached the browser. It is safe to retry.");
66117
66340
  }
@@ -66211,7 +66434,9 @@ async function startPeer(opts) {
66211
66434
  let rejectFirstReady;
66212
66435
  let sessionPromise;
66213
66436
  let sessionPromiseSettled = false;
66437
+ let retryableRefusal = false;
66214
66438
  function resetSessionPromise() {
66439
+ retryableRefusal = false;
66215
66440
  sessionPromiseSettled = false;
66216
66441
  sessionPromise = new Promise((resolve2, reject) => {
66217
66442
  resolveFirstReady = (st) => {
@@ -66308,6 +66533,8 @@ async function startPeer(opts) {
66308
66533
  raw = JSON.parse(data.toString());
66309
66534
  const frame = validateFrame(raw);
66310
66535
  if (frame.type === "hello" && frame.role === "extension") {
66536
+ if (retryableRefusal)
66537
+ resetSessionPromise();
66311
66538
  extensionHello = frame;
66312
66539
  const mintedKeypair = await generateSessionKeypair();
66313
66540
  const mintedHello = await buildServerHello({
@@ -66337,6 +66564,8 @@ async function startPeer(opts) {
66337
66564
  session = null;
66338
66565
  if (sessionPromiseSettled)
66339
66566
  resetSessionPromise();
66567
+ } else if (retryableRefusal) {
66568
+ resetSessionPromise();
66340
66569
  }
66341
66570
  extensionDisconnectListeners.forEach((cb) => cb());
66342
66571
  return;
@@ -66358,7 +66587,7 @@ async function startPeer(opts) {
66358
66587
  const extNonce = fromB64(authenticated.sessionNonce);
66359
66588
  const shared = await ecdhX25519(held.priv, extPub);
66360
66589
  const salt = await transcriptHash(held.nonce, extNonce, held.pub, extPub);
66361
- const sessionKey = await hkdfSha256(shared, salt, enc5.encode(HKDF_SESSION_INFO), 32);
66590
+ const sessionKey = await hkdfSha256(shared, salt, enc6.encode(HKDF_SESSION_INFO), 32);
66362
66591
  if (sessionEphemeral !== held) {
66363
66592
  console.warn(`[fetchproxy] ${opts.serverName}: dropping a session derived against an ephemeral that was superseded while it was being derived`);
66364
66593
  return;
@@ -66371,16 +66600,24 @@ async function startPeer(opts) {
66371
66600
  if (isRenegotiation) {
66372
66601
  renegotiateListeners.forEach((cb) => cb());
66373
66602
  } else {
66603
+ if (retryableRefusal)
66604
+ resetSessionPromise();
66374
66605
  resolveFirstReady(session);
66375
66606
  }
66376
66607
  return;
66377
66608
  }
66378
66609
  if (frame.type === "hello-rejected" && frame.mcpId === opts.mcpId) {
66379
- rejectFirstReady(new FetchproxyHelloRejectedError({
66610
+ const refusal = new FetchproxyHelloRejectedError({
66380
66611
  mcpId: frame.mcpId,
66381
66612
  reason: frame.reason,
66382
66613
  platform: extensionHello?.platform ?? null
66383
- }));
66614
+ });
66615
+ if (retryableRefusal)
66616
+ resetSessionPromise();
66617
+ const settlesPending = !sessionPromiseSettled;
66618
+ rejectFirstReady(refusal);
66619
+ if (refusal.retryable && settlesPending)
66620
+ retryableRefusal = true;
66384
66621
  }
66385
66622
  if (frame.type === "pair-pending" && frame.mcpId === opts.mcpId) {
66386
66623
  const hello2 = extensionHello;
@@ -66544,8 +66781,9 @@ function classifyFetchError(error62, code2) {
66544
66781
 
66545
66782
  // node_modules/@fetchproxy/server/dist/classify-bridge-error.js
66546
66783
  function classifyBridgeError(err) {
66547
- if (err instanceof FetchproxyHelloRejectedError)
66548
- return "hello_rejected";
66784
+ if (err instanceof FetchproxyHelloRejectedError) {
66785
+ return err.retryable ? "awaiting_approval" : "hello_rejected";
66786
+ }
66549
66787
  if (err instanceof FetchproxySessionNotReadyError)
66550
66788
  return "session_not_ready";
66551
66789
  if (err instanceof FetchproxyTimeoutError)
@@ -69330,7 +69568,7 @@ function isBrowserCapabilityGap(e) {
69330
69568
  // package.json
69331
69569
  var package_default = {
69332
69570
  name: "honeybook-mcp",
69333
- version: "1.2.3",
69571
+ version: "1.2.4",
69334
69572
  mcpName: "io.github.chrischall/honeybook-mcp",
69335
69573
  description: "HoneyBook client-portal MCP server for Claude",
69336
69574
  author: "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -69374,15 +69612,15 @@ var package_default = {
69374
69612
  typecheck: "tsc -p tsconfig.json --noEmit"
69375
69613
  },
69376
69614
  dependencies: {
69377
- "@chrischall/mcp-utils": "^2.13.0",
69615
+ "@chrischall/mcp-utils": "^2.14.0",
69378
69616
  "@fetchproxy/bootstrap": "^3.4.1",
69379
69617
  "@fetchproxy/server": "^3.4.1",
69380
- "@modelcontextprotocol/server": "^2.2.0",
69618
+ "@modelcontextprotocol/server": "^2.3.0",
69381
69619
  dotenv: "^18.0.2",
69382
69620
  zod: "^4.6.5"
69383
69621
  },
69384
69622
  devDependencies: {
69385
- "@modelcontextprotocol/client": "^2.2.0",
69623
+ "@modelcontextprotocol/client": "^2.3.0",
69386
69624
  "@types/node": "^26.0.0",
69387
69625
  "@vitest/coverage-v8": "^5.0.0",
69388
69626
  esbuild: "^0.28.0",
@@ -71261,7 +71499,7 @@ var __dirname = dirname3(fileURLToPath(import.meta.url));
71261
71499
  await loadDotenvSafely({ path: join9(__dirname, "..", ".env"), override: false });
71262
71500
  await runMcp({
71263
71501
  name: "honeybook-mcp",
71264
- version: "1.2.3",
71502
+ version: "1.2.4",
71265
71503
  // x-release-please-version
71266
71504
  tools: [
71267
71505
  registerSessionTools,
@@ -71283,7 +71521,7 @@ await runMcp({
71283
71521
  });
71284
71522
  /*! Bundled license information:
71285
71523
 
71286
- @modelcontextprotocol/server/dist/src-BHSMhZ_W.mjs:
71524
+ @modelcontextprotocol/server/dist/src-Cqbh3MYc.mjs:
71287
71525
  (*!
71288
71526
  * content-type
71289
71527
  * Copyright(c) 2015 Douglas Christopher Wilson
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import { registerAttachmentTools } from './tools/attachments.js';
20
20
  import { registerPaymentTools } from './tools/payments.js';
21
21
  await runMcp({
22
22
  name: 'honeybook-mcp',
23
- version: '1.2.3', // x-release-please-version
23
+ version: '1.2.4', // x-release-please-version
24
24
  tools: [
25
25
  registerSessionTools,
26
26
  registerFlowTools,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "honeybook-mcp",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "mcpName": "io.github.chrischall/honeybook-mcp",
5
5
  "description": "HoneyBook client-portal MCP server for Claude",
6
6
  "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -44,15 +44,15 @@
44
44
  "typecheck": "tsc -p tsconfig.json --noEmit"
45
45
  },
46
46
  "dependencies": {
47
- "@chrischall/mcp-utils": "^2.13.0",
47
+ "@chrischall/mcp-utils": "^2.14.0",
48
48
  "@fetchproxy/bootstrap": "^3.4.1",
49
49
  "@fetchproxy/server": "^3.4.1",
50
- "@modelcontextprotocol/server": "^2.2.0",
50
+ "@modelcontextprotocol/server": "^2.3.0",
51
51
  "dotenv": "^18.0.2",
52
52
  "zod": "^4.6.5"
53
53
  },
54
54
  "devDependencies": {
55
- "@modelcontextprotocol/client": "^2.2.0",
55
+ "@modelcontextprotocol/client": "^2.3.0",
56
56
  "@types/node": "^26.0.0",
57
57
  "@vitest/coverage-v8": "^5.0.0",
58
58
  "esbuild": "^0.28.0",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/chrischall/honeybook-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "1.2.3",
9
+ "version": "1.2.4",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "honeybook-mcp",
14
- "version": "1.2.3",
14
+ "version": "1.2.4",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },