honeybook-mcp 0.4.6 → 0.6.0

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": "0.4.6"
10
+ "version": "0.6.0"
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": "0.4.6",
18
+ "version": "0.6.0",
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": "0.4.6",
4
+ "version": "0.6.0",
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
@@ -3313,8 +3313,8 @@ var require_utils = __commonJS({
3313
3313
  var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
3314
3314
  var HOST_DELIM_RE = /[@/?#:]/g;
3315
3315
  var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
3316
- function reescapeHostDelimiters(host, isIP) {
3317
- const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
3316
+ function reescapeHostDelimiters(host, isIP2) {
3317
+ const re = isIP2 ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
3318
3318
  re.lastIndex = 0;
3319
3319
  return host.replace(re, (ch) => HOST_DELIMS[ch]);
3320
3320
  }
@@ -3803,7 +3803,7 @@ var require_fast_uri = __commonJS({
3803
3803
  fragment: void 0
3804
3804
  };
3805
3805
  let malformedAuthorityOrPort = false;
3806
- let isIP = false;
3806
+ let isIP2 = false;
3807
3807
  if (options.reference === "suffix") {
3808
3808
  if (options.scheme) {
3809
3809
  uri = options.scheme + ":" + uri;
@@ -3852,9 +3852,9 @@ var require_fast_uri = __commonJS({
3852
3852
  if (ipv4result === false) {
3853
3853
  const ipv6result = normalizeIPv6(parsed.host);
3854
3854
  parsed.host = ipv6result.host.toLowerCase();
3855
- isIP = ipv6result.isIPV6;
3855
+ isIP2 = ipv6result.isIPV6;
3856
3856
  } else {
3857
- isIP = true;
3857
+ isIP2 = true;
3858
3858
  }
3859
3859
  }
3860
3860
  if (parsed.scheme === void 0 && parsed.userinfo === void 0 && parsed.host === void 0 && parsed.port === void 0 && parsed.query === void 0 && !parsed.path) {
@@ -3871,7 +3871,7 @@ var require_fast_uri = __commonJS({
3871
3871
  }
3872
3872
  const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
3873
3873
  if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
3874
- if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
3874
+ if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP2 === false && nonSimpleDomain(parsed.host)) {
3875
3875
  try {
3876
3876
  parsed.host = new URL("http://" + parsed.host).hostname;
3877
3877
  } catch (e) {
@@ -3885,7 +3885,7 @@ var require_fast_uri = __commonJS({
3885
3885
  parsed.scheme = unescape(parsed.scheme);
3886
3886
  }
3887
3887
  if (parsed.host !== void 0) {
3888
- parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
3888
+ parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP2);
3889
3889
  }
3890
3890
  }
3891
3891
  if (parsed.path) {
@@ -7198,7 +7198,7 @@ var require_permessage_deflate = __commonJS({
7198
7198
  acceptAsServer(offers) {
7199
7199
  const opts = this._options;
7200
7200
  const accepted = offers.find((params) => {
7201
- if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) {
7201
+ if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && (typeof params.client_max_window_bits === "number" ? opts.clientMaxWindowBits > params.client_max_window_bits : !params.client_max_window_bits)) {
7202
7202
  return false;
7203
7203
  }
7204
7204
  return true;
@@ -34680,55 +34680,19 @@ var StdioServerTransport = class {
34680
34680
  }
34681
34681
  };
34682
34682
 
34683
- // node_modules/@chrischall/mcp-utils/dist/server/index.js
34684
- async function createMcpServer(opts) {
34685
- const server = new McpServer({ name: opts.name, version: opts.version });
34686
- if (opts.banner !== void 0) {
34687
- console.error(opts.banner);
34688
- }
34689
- const deps = opts.deps;
34690
- for (const register of opts.tools) {
34691
- await register(server, deps);
34692
- }
34693
- return server;
34694
- }
34695
- function withGracefulShutdown(server, opts = {}) {
34696
- const shouldExit = opts.exit ?? true;
34697
- let shuttingDown = false;
34698
- const handler = (signal) => {
34699
- if (shuttingDown)
34700
- return;
34701
- shuttingDown = true;
34702
- void (async () => {
34703
- try {
34704
- if (opts.onSignal)
34705
- await opts.onSignal(signal);
34706
- await server.close();
34707
- } catch (err) {
34708
- console.error(`[mcp-utils] error during graceful shutdown on ${signal}: ${err instanceof Error ? err.message : String(err)}`);
34709
- } finally {
34710
- if (shouldExit)
34711
- process.exit(0);
34712
- }
34713
- })();
34714
- };
34715
- process.on("SIGINT", () => handler("SIGINT"));
34716
- process.on("SIGTERM", () => handler("SIGTERM"));
34717
- }
34718
- async function runMcp(opts) {
34719
- const server = await createMcpServer(opts);
34720
- const shutdown = opts.shutdown ?? true;
34721
- if (shutdown !== false) {
34722
- withGracefulShutdown(server, shutdown === true ? {} : shutdown);
34723
- }
34724
- const spec = opts.transport ?? "stdio";
34725
- const transport = spec === "stdio" ? new StdioServerTransport() : spec;
34726
- await server.connect(transport);
34727
- return server;
34728
- }
34729
-
34730
34683
  // node_modules/@chrischall/mcp-utils/dist/errors/index.js
34731
34684
  var DEFAULT_ERROR_MESSAGE_MAX = 500;
34685
+ var McpToolError = class extends Error {
34686
+ /** Actionable remediation text, when one applies. */
34687
+ hint;
34688
+ constructor(message, opts) {
34689
+ super(message, opts?.cause !== void 0 ? { cause: opts.cause } : void 0);
34690
+ this.name = "McpToolError";
34691
+ if (opts?.hint !== void 0)
34692
+ this.hint = opts.hint;
34693
+ Object.setPrototypeOf(this, new.target.prototype);
34694
+ }
34695
+ };
34732
34696
  var BEARER_RE = /(bearer\s+)[A-Za-z0-9._~+/=-]{8,}/gi;
34733
34697
  var JWT_RE = /\b[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{8,}\b/g;
34734
34698
  var BASIC_AUTH_RE = /(authorization\s*:\s*basic\s+)[A-Za-z0-9+/=_-]{6,}/gi;
@@ -34778,6 +34742,81 @@ function textResult(data) {
34778
34742
  function rawTextResult(text) {
34779
34743
  return { content: [{ type: "text", text }] };
34780
34744
  }
34745
+ function errorResult(message) {
34746
+ return {
34747
+ content: [{ type: "text", text: redactSecrets(message) }],
34748
+ isError: true
34749
+ };
34750
+ }
34751
+
34752
+ // node_modules/@chrischall/mcp-utils/dist/server/index.js
34753
+ function hintResultOrRethrow(err) {
34754
+ if (err instanceof McpToolError && err.hint) {
34755
+ return errorResult(`${err.message}
34756
+
34757
+ Hint: ${err.hint}`);
34758
+ }
34759
+ throw err;
34760
+ }
34761
+ function surfaceToolHints(server) {
34762
+ const register = server.registerTool.bind(server);
34763
+ server.registerTool = (name, config2, cb) => register(name, config2, (...args) => {
34764
+ let result;
34765
+ try {
34766
+ result = cb(...args);
34767
+ } catch (err) {
34768
+ return hintResultOrRethrow(err);
34769
+ }
34770
+ return result instanceof Promise ? result.catch(hintResultOrRethrow) : result;
34771
+ });
34772
+ }
34773
+ async function createMcpServer(opts) {
34774
+ const server = new McpServer({ name: opts.name, version: opts.version });
34775
+ if (opts.surfaceHints !== false)
34776
+ surfaceToolHints(server);
34777
+ if (opts.banner !== void 0) {
34778
+ console.error(opts.banner);
34779
+ }
34780
+ const deps = opts.deps;
34781
+ for (const register of opts.tools) {
34782
+ await register(server, deps);
34783
+ }
34784
+ return server;
34785
+ }
34786
+ function withGracefulShutdown(server, opts = {}) {
34787
+ const shouldExit = opts.exit ?? true;
34788
+ let shuttingDown = false;
34789
+ const handler = (signal) => {
34790
+ if (shuttingDown)
34791
+ return;
34792
+ shuttingDown = true;
34793
+ void (async () => {
34794
+ try {
34795
+ if (opts.onSignal)
34796
+ await opts.onSignal(signal);
34797
+ await server.close();
34798
+ } catch (err) {
34799
+ console.error(`[mcp-utils] error during graceful shutdown on ${signal}: ${err instanceof Error ? err.message : String(err)}`);
34800
+ } finally {
34801
+ if (shouldExit)
34802
+ process.exit(0);
34803
+ }
34804
+ })();
34805
+ };
34806
+ process.on("SIGINT", () => handler("SIGINT"));
34807
+ process.on("SIGTERM", () => handler("SIGTERM"));
34808
+ }
34809
+ async function runMcp(opts) {
34810
+ const server = await createMcpServer(opts);
34811
+ const shutdown = opts.shutdown ?? true;
34812
+ if (shutdown !== false) {
34813
+ withGracefulShutdown(server, shutdown === true ? {} : shutdown);
34814
+ }
34815
+ const spec = opts.transport ?? "stdio";
34816
+ const transport = spec === "stdio" ? new StdioServerTransport() : spec;
34817
+ await server.connect(transport);
34818
+ return server;
34819
+ }
34781
34820
 
34782
34821
  // node_modules/@chrischall/mcp-utils/dist/config/index.js
34783
34822
  var PLACEHOLDER_RE = /^\$\{[^}]*\}$/;
@@ -37141,6 +37180,27 @@ function classifyBridgeError(err) {
37141
37180
  }
37142
37181
 
37143
37182
  // node_modules/@fetchproxy/server/dist/ws-server.js
37183
+ import { isIP } from "node:net";
37184
+ function envWsPort() {
37185
+ const raw = process.env.FETCHPROXY_WS_PORT;
37186
+ if (raw === void 0 || raw.trim() === "")
37187
+ return void 0;
37188
+ if (!/^\d+$/.test(raw.trim()))
37189
+ return void 0;
37190
+ const port = Number(raw.trim());
37191
+ if (!Number.isInteger(port) || port < 1 || port > 65535)
37192
+ return void 0;
37193
+ return port;
37194
+ }
37195
+ function envWsHost() {
37196
+ const raw = process.env.FETCHPROXY_WS_HOST;
37197
+ if (raw === void 0)
37198
+ return void 0;
37199
+ const host = raw.trim();
37200
+ if (host === "" || isIP(host) === 0)
37201
+ return void 0;
37202
+ return host;
37203
+ }
37144
37204
  var FetchproxyProtocolError = class extends Error {
37145
37205
  constructor(message) {
37146
37206
  super(message);
@@ -37388,8 +37448,8 @@ var FetchproxyServer = class {
37388
37448
  }
37389
37449
  }
37390
37450
  this.opts = {
37391
- port: opts.port ?? 37149,
37392
- host: opts.host ?? "127.0.0.1",
37451
+ port: opts.port ?? envWsPort() ?? 37149,
37452
+ host: opts.host ?? envWsHost() ?? "127.0.0.1",
37393
37453
  serverName: opts.serverName,
37394
37454
  version: opts.version,
37395
37455
  domains: [...opts.domains],
@@ -37675,6 +37735,7 @@ var FetchproxyServer = class {
37675
37735
  return {
37676
37736
  role: this.role,
37677
37737
  port: this.opts.port,
37738
+ host: this.opts.host,
37678
37739
  serverVersion: this.opts.version,
37679
37740
  fetchTimeoutMs: this.opts.fetchTimeoutMs ?? 0,
37680
37741
  bridgeReviveDelayMs: this.opts.bridgeReviveDelayMs ?? 0,
@@ -39201,7 +39262,7 @@ function bridgeErrorInfo(err) {
39201
39262
  // package.json
39202
39263
  var package_default = {
39203
39264
  name: "honeybook-mcp",
39204
- version: "0.4.6",
39265
+ version: "0.6.0",
39205
39266
  mcpName: "io.github.chrischall/honeybook-mcp",
39206
39267
  description: "HoneyBook client-portal MCP server for Claude",
39207
39268
  author: "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -39224,7 +39285,8 @@ var package_default = {
39224
39285
  ".claude-plugin",
39225
39286
  "skills",
39226
39287
  ".mcp.json",
39227
- "server.json"
39288
+ "server.json",
39289
+ "mint.yaml"
39228
39290
  ],
39229
39291
  engines: {
39230
39292
  node: ">=20.6.0"
@@ -39237,13 +39299,14 @@ var package_default = {
39237
39299
  build: "tsc && npm run bundle",
39238
39300
  bundle: `esbuild src/index.ts --bundle --platform=node --format=esm --external:dotenv --banner:js='import { createRequire as __createRequire } from "module"; const require = __createRequire(import.meta.url);' --outfile=dist/bundle.js`,
39239
39301
  dev: "node --env-file=.env dist/index.js",
39240
- test: "vitest run",
39241
- "test:watch": "vitest"
39302
+ test: "npm run typecheck && vitest run",
39303
+ "test:watch": "vitest",
39304
+ typecheck: "tsc -p tsconfig.json --noEmit"
39242
39305
  },
39243
39306
  dependencies: {
39244
- "@chrischall/mcp-utils": "^0.14.0",
39245
- "@fetchproxy/bootstrap": "^2.0.0",
39246
- "@fetchproxy/server": "^2.0.0",
39307
+ "@chrischall/mcp-utils": "^0.15.0",
39308
+ "@fetchproxy/bootstrap": "^2.2.0",
39309
+ "@fetchproxy/server": "^2.2.0",
39247
39310
  "@modelcontextprotocol/sdk": "^1.29.0",
39248
39311
  dotenv: "^17.4.2",
39249
39312
  zod: "^4.4.3"
@@ -39841,7 +39904,7 @@ var __dirname = dirname2(fileURLToPath(import.meta.url));
39841
39904
  await loadDotenvSafely({ path: join4(__dirname, "..", ".env"), override: false });
39842
39905
  await runMcp({
39843
39906
  name: "honeybook-mcp",
39844
- version: "0.4.6",
39907
+ version: "0.6.0",
39845
39908
  // x-release-please-version
39846
39909
  tools: [
39847
39910
  registerSessionTools,
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import { registerContractTools } from './tools/contracts.js';
11
11
  import { registerInvoiceTools } from './tools/invoices.js';
12
12
  await runMcp({
13
13
  name: 'honeybook-mcp',
14
- version: '0.4.6', // x-release-please-version
14
+ version: '0.6.0', // x-release-please-version
15
15
  tools: [
16
16
  registerSessionTools,
17
17
  registerWorkspaceFileTools,
package/mint.yaml ADDED
@@ -0,0 +1,45 @@
1
+ version: 1
2
+ name: HoneyBook
3
+ slug: honeybook
4
+ summary: >-
5
+ HoneyBook client-portal MCP — view wedding-vendor contracts and invoices
6
+ #
7
+ # Hosting note (a comment, not user-facing summary text): this is a
8
+ # BROWSER-BRIDGE MCP — it reaches its site through the user's signed-in
9
+ # tab via the fetchproxy bridge. A bridged registration also needs runtime
10
+ # `fly-shared`, `bridge: true` and a `bridgePortEnv`, which are registration
11
+ # fields this manifest has no schema for (set them over the control API).
12
+ # `state.dataDir` below is required for `bridge`.
13
+ env:
14
+ - name: HONEYBOOK_API_VERSION
15
+ required: false
16
+ help: >-
17
+ Pins the HoneyBook API version instead of detecting it at startup. Leave
18
+ unset unless a detection failure needs working around.
19
+ - name: HONEYBOOK_DISABLE_FETCHPROXY
20
+ required: false
21
+ help: >-
22
+ Set to 1 to disable the browser-bridge fallback, making missing
23
+ credentials a hard error. Recommended for a hosted registration, which has
24
+ no browser to fall back to.
25
+ - name: HONEYBOOK_SESSIONS_DIR
26
+ required: false
27
+ help: >-
28
+ Directory for persisted session/cache state. Relates to state.dataDir
29
+ below; leave unset to use the default under $HOME.
30
+ state:
31
+ dataDir: true
32
+ reason: >-
33
+ The fetchproxy identity lives at $HOME/.fetchproxy/identity/<name>.json
34
+ and the pair code derives from it. Without a persistent $HOME every cold
35
+ start mints a fresh identity and re-prompts pairing in the browser; the
36
+ API refuses bridge without it.
37
+ egress:
38
+ allow:
39
+ # Only hosts the SERVER process actually fetches. Hosts that appear
40
+ # solely in a URL this server BUILDS and returns are excluded.
41
+ # ONLY the API host: client.ts fetches `${API_BASE}` = https://api.honeybook.com
42
+ # for every call. honeybook.com and hbportal.co are declared to the
43
+ # fetchproxy BRIDGE — the browser reaches those, not this process — so they
44
+ # are not server egress.
45
+ - api.honeybook.com
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "honeybook-mcp",
3
- "version": "0.4.6",
3
+ "version": "0.6.0",
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>",
@@ -23,7 +23,8 @@
23
23
  ".claude-plugin",
24
24
  "skills",
25
25
  ".mcp.json",
26
- "server.json"
26
+ "server.json",
27
+ "mint.yaml"
27
28
  ],
28
29
  "engines": {
29
30
  "node": ">=20.6.0"
@@ -36,13 +37,14 @@
36
37
  "build": "tsc && npm run bundle",
37
38
  "bundle": "esbuild src/index.ts --bundle --platform=node --format=esm --external:dotenv --banner:js='import { createRequire as __createRequire } from \"module\"; const require = __createRequire(import.meta.url);' --outfile=dist/bundle.js",
38
39
  "dev": "node --env-file=.env dist/index.js",
39
- "test": "vitest run",
40
- "test:watch": "vitest"
40
+ "test": "npm run typecheck && vitest run",
41
+ "test:watch": "vitest",
42
+ "typecheck": "tsc -p tsconfig.json --noEmit"
41
43
  },
42
44
  "dependencies": {
43
- "@chrischall/mcp-utils": "^0.14.0",
44
- "@fetchproxy/bootstrap": "^2.0.0",
45
- "@fetchproxy/server": "^2.0.0",
45
+ "@chrischall/mcp-utils": "^0.15.0",
46
+ "@fetchproxy/bootstrap": "^2.2.0",
47
+ "@fetchproxy/server": "^2.2.0",
46
48
  "@modelcontextprotocol/sdk": "^1.29.0",
47
49
  "dotenv": "^17.4.2",
48
50
  "zod": "^4.4.3"
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": "0.4.6",
9
+ "version": "0.6.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "honeybook-mcp",
14
- "version": "0.4.6",
14
+ "version": "0.6.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },