@buoy-gg/mcp 7.0.34 → 7.0.36

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.
@@ -614,7 +614,7 @@ async function waitForBroker(url, attempts = 20) {
614
614
  var delay = (ms) => new Promise((r) => setTimeout(r, ms));
615
615
 
616
616
  // src/version.ts
617
- var VERSION = "7.0.34" ? "7.0.34" : "0.0.0-dev";
617
+ var VERSION = "7.0.36" ? "7.0.36" : "0.0.0-dev";
618
618
  var PACKAGE_NAME = "@buoy-gg/mcp";
619
619
 
620
620
  // src/update/checkForUpdate.ts
@@ -2745,6 +2745,9 @@ _\u{1F4CC} pinned \xB7 \u{1F516} saved. Act on one with its id, e.g. network_act
2745
2745
  body: z13.union([z13.string(), z13.record(z13.unknown()), z13.array(z13.unknown())]).optional().describe(
2746
2746
  "For kind 'respond': the response body. Pass JSON directly (an object or array) or a raw string; content-type is inferred."
2747
2747
  ),
2748
+ bodyPatch: z13.record(z13.unknown()).optional().describe(
2749
+ 'For `add` with `fromRequestId` (or a rule `id`): fields deep-merged INTO the real captured response \u2014 the way to change one field of a big payload without pasting it back. Send only what changes, e.g. {"name":"test123"}. Ignored when `body` is given.'
2750
+ ),
2748
2751
  statusText: z13.string().optional().describe(
2749
2752
  "For kind 'respond': the status line's text, e.g. 'Service Unavailable'. Cosmetic \u2014 React Native's XMLHttpRequest has no statusText field, so the app never sees it; it only makes the developer's rule list read correctly."
2750
2753
  ),
@@ -2796,6 +2799,7 @@ _\u{1F4CC} pinned \xB7 \u{1F516} saved. Act on one with its id, e.g. network_act
2796
2799
  status: args.status,
2797
2800
  statusText: args.statusText,
2798
2801
  body: args.body,
2802
+ bodyPatch: args.bodyPatch,
2799
2803
  headers: args.headers,
2800
2804
  failKind: args.failKind,
2801
2805
  delayMs: args.delayMs,
@@ -4013,13 +4017,21 @@ function registerInteractTools(server, sync) {
4013
4017
  description: "List the interactive / labeled elements currently on screen \u2014 the app's live accessibility-style tree walked from the React fiber tree. Each row shows the component name, visible text/label, role, testID, a normalized tap point (tap: x,y in 0\u20131), and its #nativeTag. Rows marked with \u2022 are tappable (have an onPress). Use this to see what's on screen and pick something to tap with tap_element \u2014 no screenshot needed. If you already know the sequence you want to drive, `run_flow` does the whole thing (taps, waits, assertions) in one call instead. Re-run after navigating or when the screen changes, since positions move. Requires Buoy Pro.",
4014
4018
  inputSchema: {
4015
4019
  interactiveOnly: z18.boolean().optional().describe("Only return tappable (onPress) elements. Default false (include labels/text for context)."),
4020
+ includeBuoy: z18.boolean().optional().describe(
4021
+ "Also list Buoy's own overlay \u2014 the dial, tool sheets, Ask Buoy's chat. Default false: the screen described is the app's. Exact testIDs inside Buoy (buoy-\u2026) can still be tapped without this."
4022
+ ),
4016
4023
  deviceId: deviceIdInput
4017
4024
  }
4018
4025
  },
4019
4026
  async (args) => {
4020
4027
  try {
4021
4028
  const target = sync.requireProDevice(args.deviceId);
4022
- const res = await sync.callAction(TOOL_ID2, "describeScreen", {}, target);
4029
+ const res = await sync.callAction(
4030
+ TOOL_ID2,
4031
+ "describeScreen",
4032
+ { includeBuoy: args.includeBuoy },
4033
+ target
4034
+ );
4023
4035
  const all = res?.elements ?? [];
4024
4036
  const elements = args.interactiveOnly ? all.filter((e) => e.interactive) : all;
4025
4037
  if (elements.length === 0) {
@@ -4027,7 +4039,8 @@ function registerInteractTools(server, sync) {
4027
4039
  "No elements found on screen. If the app just navigated, wait a moment and retry; make sure highlight-updates is enabled in the app."
4028
4040
  );
4029
4041
  }
4030
- const header = `Screen ${res.screen.width}\xD7${res.screen.height} \u2014 ${elements.length} element${elements.length === 1 ? "" : "s"} (\u2022 = tappable). Tap with tap_element({ testID | query | nativeTag }).`;
4042
+ const hidden = res.hiddenBuoy ? ` Buoy's own overlay (${res.hiddenBuoy} element${res.hiddenBuoy === 1 ? "" : "s"}) is left out \u2014 pass includeBuoy:true to see it.` : "";
4043
+ const header = `Screen ${res.screen.width}\xD7${res.screen.height} \u2014 ${elements.length} element${elements.length === 1 ? "" : "s"} (\u2022 = tappable). Tap with tap_element({ testID | query | nativeTag }).${hidden}`;
4031
4044
  return text5(`${header}
4032
4045
 
4033
4046
  ${elements.map(formatElement).join("\n")}`);
@@ -4048,6 +4061,7 @@ ${elements.map(formatElement).join("\n")}`);
4048
4061
  text: z18.string().optional().describe("For a text input: the string to set via onChangeText."),
4049
4062
  longPress: z18.boolean().optional().describe("Invoke the element's onLongPress instead of onPress. Fails with a clear reason if the element has no onLongPress handler."),
4050
4063
  scrollIntoView: z18.boolean().optional().describe("Scroll the target into view first if it's off-screen. Default true."),
4064
+ includeBuoy: z18.boolean().optional().describe("Let a fuzzy `query` match Buoy's own overlay. Default false \u2014 an exact nativeTag/testID always may."),
4051
4065
  deviceId: deviceIdInput
4052
4066
  }
4053
4067
  },
@@ -4067,7 +4081,8 @@ ${elements.map(formatElement).join("\n")}`);
4067
4081
  value: args.value,
4068
4082
  text: args.text,
4069
4083
  longPress: args.longPress,
4070
- scrollIntoView: args.scrollIntoView
4084
+ scrollIntoView: args.scrollIntoView,
4085
+ includeBuoy: args.includeBuoy
4071
4086
  },
4072
4087
  target
4073
4088
  );
@@ -4079,7 +4094,12 @@ ${elements.map(formatElement).join("\n")}`);
4079
4094
  const id = m.testID ? ` [testID=${m.testID}]` : m.nativeTag != null ? ` #${m.nativeTag}` : "";
4080
4095
  const scrolledNote = res.scrolled ? " (scrolled into view)" : "";
4081
4096
  const verb = m.via === "onValueChange" ? `Set "${label}"${id} \u2192 ${JSON.stringify(m.value)}` : m.via === "onChangeText" ? `Typed ${JSON.stringify(m.value)} into "${label}"${id}` : m.via === "onLongPress" ? `Long-pressed "${label}"${id}` : `Tapped "${label}"${id}`;
4082
- return text5(`${verb}${scrolledNote}.${flowTip}`);
4097
+ const fx = res.effect;
4098
+ const effectNote = !fx ? "" : fx.commits > 0 ? ` ${fx.commits} re-render${fx.commits === 1 ? "" : "s"} followed.` : ` No re-render followed within ${fx.observedMs}ms \u2014 the handler ran but the app did not react. The element may sit on a screen beneath the current one, or be inert; do not treat this as done.`;
4099
+ const alsoNote = res.alsoMatched?.length ? `
4100
+ Also matched equally well (the choice was a coin toss \u2014 re-tap by #nativeTag if this was wrong):
4101
+ ` + res.alsoMatched.map((c) => `- ${c.name}${c.text ? ` "${c.text}"` : ""}${c.testID ? ` [testID=${c.testID}]` : ""}${c.nativeTag != null ? ` #${c.nativeTag}` : ""}`).join("\n") : "";
4102
+ return text5(`${verb}${scrolledNote}.${effectNote}${alsoNote}${flowTip}`);
4083
4103
  }
4084
4104
  let msg = res?.reason ?? "Tap failed.";
4085
4105
  if (res?.candidates?.length) {
package/dist/cli.js CHANGED
@@ -652,7 +652,7 @@ var import_node_os = __toESM(require("os"));
652
652
  var import_node_path = __toESM(require("path"));
653
653
 
654
654
  // src/version.ts
655
- var VERSION = "7.0.34" ? "7.0.34" : "0.0.0-dev";
655
+ var VERSION = "7.0.36" ? "7.0.36" : "0.0.0-dev";
656
656
  var PACKAGE_NAME = "@buoy-gg/mcp";
657
657
 
658
658
  // src/update/checkForUpdate.ts
@@ -1979,6 +1979,9 @@ _\u{1F4CC} pinned \xB7 \u{1F516} saved. Act on one with its id, e.g. network_act
1979
1979
  body: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.record(import_zod5.z.unknown()), import_zod5.z.array(import_zod5.z.unknown())]).optional().describe(
1980
1980
  "For kind 'respond': the response body. Pass JSON directly (an object or array) or a raw string; content-type is inferred."
1981
1981
  ),
1982
+ bodyPatch: import_zod5.z.record(import_zod5.z.unknown()).optional().describe(
1983
+ 'For `add` with `fromRequestId` (or a rule `id`): fields deep-merged INTO the real captured response \u2014 the way to change one field of a big payload without pasting it back. Send only what changes, e.g. {"name":"test123"}. Ignored when `body` is given.'
1984
+ ),
1982
1985
  statusText: import_zod5.z.string().optional().describe(
1983
1986
  "For kind 'respond': the status line's text, e.g. 'Service Unavailable'. Cosmetic \u2014 React Native's XMLHttpRequest has no statusText field, so the app never sees it; it only makes the developer's rule list read correctly."
1984
1987
  ),
@@ -2030,6 +2033,7 @@ _\u{1F4CC} pinned \xB7 \u{1F516} saved. Act on one with its id, e.g. network_act
2030
2033
  status: args.status,
2031
2034
  statusText: args.statusText,
2032
2035
  body: args.body,
2036
+ bodyPatch: args.bodyPatch,
2033
2037
  headers: args.headers,
2034
2038
  failKind: args.failKind,
2035
2039
  delayMs: args.delayMs,
@@ -4043,13 +4047,21 @@ function registerInteractTools(server, sync) {
4043
4047
  description: "List the interactive / labeled elements currently on screen \u2014 the app's live accessibility-style tree walked from the React fiber tree. Each row shows the component name, visible text/label, role, testID, a normalized tap point (tap: x,y in 0\u20131), and its #nativeTag. Rows marked with \u2022 are tappable (have an onPress). Use this to see what's on screen and pick something to tap with tap_element \u2014 no screenshot needed. If you already know the sequence you want to drive, `run_flow` does the whole thing (taps, waits, assertions) in one call instead. Re-run after navigating or when the screen changes, since positions move. Requires Buoy Pro.",
4044
4048
  inputSchema: {
4045
4049
  interactiveOnly: import_zod18.z.boolean().optional().describe("Only return tappable (onPress) elements. Default false (include labels/text for context)."),
4050
+ includeBuoy: import_zod18.z.boolean().optional().describe(
4051
+ "Also list Buoy's own overlay \u2014 the dial, tool sheets, Ask Buoy's chat. Default false: the screen described is the app's. Exact testIDs inside Buoy (buoy-\u2026) can still be tapped without this."
4052
+ ),
4046
4053
  deviceId: deviceIdInput
4047
4054
  }
4048
4055
  },
4049
4056
  async (args) => {
4050
4057
  try {
4051
4058
  const target = sync.requireProDevice(args.deviceId);
4052
- const res = await sync.callAction(TOOL_ID2, "describeScreen", {}, target);
4059
+ const res = await sync.callAction(
4060
+ TOOL_ID2,
4061
+ "describeScreen",
4062
+ { includeBuoy: args.includeBuoy },
4063
+ target
4064
+ );
4053
4065
  const all = res?.elements ?? [];
4054
4066
  const elements = args.interactiveOnly ? all.filter((e) => e.interactive) : all;
4055
4067
  if (elements.length === 0) {
@@ -4057,7 +4069,8 @@ function registerInteractTools(server, sync) {
4057
4069
  "No elements found on screen. If the app just navigated, wait a moment and retry; make sure highlight-updates is enabled in the app."
4058
4070
  );
4059
4071
  }
4060
- const header = `Screen ${res.screen.width}\xD7${res.screen.height} \u2014 ${elements.length} element${elements.length === 1 ? "" : "s"} (\u2022 = tappable). Tap with tap_element({ testID | query | nativeTag }).`;
4072
+ const hidden = res.hiddenBuoy ? ` Buoy's own overlay (${res.hiddenBuoy} element${res.hiddenBuoy === 1 ? "" : "s"}) is left out \u2014 pass includeBuoy:true to see it.` : "";
4073
+ const header = `Screen ${res.screen.width}\xD7${res.screen.height} \u2014 ${elements.length} element${elements.length === 1 ? "" : "s"} (\u2022 = tappable). Tap with tap_element({ testID | query | nativeTag }).${hidden}`;
4061
4074
  return text5(`${header}
4062
4075
 
4063
4076
  ${elements.map(formatElement).join("\n")}`);
@@ -4078,6 +4091,7 @@ ${elements.map(formatElement).join("\n")}`);
4078
4091
  text: import_zod18.z.string().optional().describe("For a text input: the string to set via onChangeText."),
4079
4092
  longPress: import_zod18.z.boolean().optional().describe("Invoke the element's onLongPress instead of onPress. Fails with a clear reason if the element has no onLongPress handler."),
4080
4093
  scrollIntoView: import_zod18.z.boolean().optional().describe("Scroll the target into view first if it's off-screen. Default true."),
4094
+ includeBuoy: import_zod18.z.boolean().optional().describe("Let a fuzzy `query` match Buoy's own overlay. Default false \u2014 an exact nativeTag/testID always may."),
4081
4095
  deviceId: deviceIdInput
4082
4096
  }
4083
4097
  },
@@ -4097,7 +4111,8 @@ ${elements.map(formatElement).join("\n")}`);
4097
4111
  value: args.value,
4098
4112
  text: args.text,
4099
4113
  longPress: args.longPress,
4100
- scrollIntoView: args.scrollIntoView
4114
+ scrollIntoView: args.scrollIntoView,
4115
+ includeBuoy: args.includeBuoy
4101
4116
  },
4102
4117
  target
4103
4118
  );
@@ -4109,7 +4124,12 @@ ${elements.map(formatElement).join("\n")}`);
4109
4124
  const id = m.testID ? ` [testID=${m.testID}]` : m.nativeTag != null ? ` #${m.nativeTag}` : "";
4110
4125
  const scrolledNote = res.scrolled ? " (scrolled into view)" : "";
4111
4126
  const verb = m.via === "onValueChange" ? `Set "${label}"${id} \u2192 ${JSON.stringify(m.value)}` : m.via === "onChangeText" ? `Typed ${JSON.stringify(m.value)} into "${label}"${id}` : m.via === "onLongPress" ? `Long-pressed "${label}"${id}` : `Tapped "${label}"${id}`;
4112
- return text5(`${verb}${scrolledNote}.${flowTip}`);
4127
+ const fx = res.effect;
4128
+ const effectNote = !fx ? "" : fx.commits > 0 ? ` ${fx.commits} re-render${fx.commits === 1 ? "" : "s"} followed.` : ` No re-render followed within ${fx.observedMs}ms \u2014 the handler ran but the app did not react. The element may sit on a screen beneath the current one, or be inert; do not treat this as done.`;
4129
+ const alsoNote = res.alsoMatched?.length ? `
4130
+ Also matched equally well (the choice was a coin toss \u2014 re-tap by #nativeTag if this was wrong):
4131
+ ` + res.alsoMatched.map((c) => `- ${c.name}${c.text ? ` "${c.text}"` : ""}${c.testID ? ` [testID=${c.testID}]` : ""}${c.nativeTag != null ? ` #${c.nativeTag}` : ""}`).join("\n") : "";
4132
+ return text5(`${verb}${scrolledNote}.${effectNote}${alsoNote}${flowTip}`);
4113
4133
  }
4114
4134
  let msg = res?.reason ?? "Tap failed.";
4115
4135
  if (res?.candidates?.length) {
package/dist/cli.mjs CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  SyncClient,
4
4
  createMcpServer,
5
5
  runInit
6
- } from "./chunk-LS2L5OOL.mjs";
6
+ } from "./chunk-QIINQPNK.mjs";
7
7
 
8
8
  // src/cli.ts
9
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/dist/index.js CHANGED
@@ -687,7 +687,7 @@ var import_node_os = __toESM(require("os"));
687
687
  var import_node_path = __toESM(require("path"));
688
688
 
689
689
  // src/version.ts
690
- var VERSION = "7.0.34" ? "7.0.34" : "0.0.0-dev";
690
+ var VERSION = "7.0.36" ? "7.0.36" : "0.0.0-dev";
691
691
  var PACKAGE_NAME = "@buoy-gg/mcp";
692
692
 
693
693
  // src/update/checkForUpdate.ts
@@ -2014,6 +2014,9 @@ _\u{1F4CC} pinned \xB7 \u{1F516} saved. Act on one with its id, e.g. network_act
2014
2014
  body: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.record(import_zod5.z.unknown()), import_zod5.z.array(import_zod5.z.unknown())]).optional().describe(
2015
2015
  "For kind 'respond': the response body. Pass JSON directly (an object or array) or a raw string; content-type is inferred."
2016
2016
  ),
2017
+ bodyPatch: import_zod5.z.record(import_zod5.z.unknown()).optional().describe(
2018
+ 'For `add` with `fromRequestId` (or a rule `id`): fields deep-merged INTO the real captured response \u2014 the way to change one field of a big payload without pasting it back. Send only what changes, e.g. {"name":"test123"}. Ignored when `body` is given.'
2019
+ ),
2017
2020
  statusText: import_zod5.z.string().optional().describe(
2018
2021
  "For kind 'respond': the status line's text, e.g. 'Service Unavailable'. Cosmetic \u2014 React Native's XMLHttpRequest has no statusText field, so the app never sees it; it only makes the developer's rule list read correctly."
2019
2022
  ),
@@ -2065,6 +2068,7 @@ _\u{1F4CC} pinned \xB7 \u{1F516} saved. Act on one with its id, e.g. network_act
2065
2068
  status: args.status,
2066
2069
  statusText: args.statusText,
2067
2070
  body: args.body,
2071
+ bodyPatch: args.bodyPatch,
2068
2072
  headers: args.headers,
2069
2073
  failKind: args.failKind,
2070
2074
  delayMs: args.delayMs,
@@ -4078,13 +4082,21 @@ function registerInteractTools(server, sync) {
4078
4082
  description: "List the interactive / labeled elements currently on screen \u2014 the app's live accessibility-style tree walked from the React fiber tree. Each row shows the component name, visible text/label, role, testID, a normalized tap point (tap: x,y in 0\u20131), and its #nativeTag. Rows marked with \u2022 are tappable (have an onPress). Use this to see what's on screen and pick something to tap with tap_element \u2014 no screenshot needed. If you already know the sequence you want to drive, `run_flow` does the whole thing (taps, waits, assertions) in one call instead. Re-run after navigating or when the screen changes, since positions move. Requires Buoy Pro.",
4079
4083
  inputSchema: {
4080
4084
  interactiveOnly: import_zod18.z.boolean().optional().describe("Only return tappable (onPress) elements. Default false (include labels/text for context)."),
4085
+ includeBuoy: import_zod18.z.boolean().optional().describe(
4086
+ "Also list Buoy's own overlay \u2014 the dial, tool sheets, Ask Buoy's chat. Default false: the screen described is the app's. Exact testIDs inside Buoy (buoy-\u2026) can still be tapped without this."
4087
+ ),
4081
4088
  deviceId: deviceIdInput
4082
4089
  }
4083
4090
  },
4084
4091
  async (args) => {
4085
4092
  try {
4086
4093
  const target = sync.requireProDevice(args.deviceId);
4087
- const res = await sync.callAction(TOOL_ID2, "describeScreen", {}, target);
4094
+ const res = await sync.callAction(
4095
+ TOOL_ID2,
4096
+ "describeScreen",
4097
+ { includeBuoy: args.includeBuoy },
4098
+ target
4099
+ );
4088
4100
  const all = res?.elements ?? [];
4089
4101
  const elements = args.interactiveOnly ? all.filter((e) => e.interactive) : all;
4090
4102
  if (elements.length === 0) {
@@ -4092,7 +4104,8 @@ function registerInteractTools(server, sync) {
4092
4104
  "No elements found on screen. If the app just navigated, wait a moment and retry; make sure highlight-updates is enabled in the app."
4093
4105
  );
4094
4106
  }
4095
- const header = `Screen ${res.screen.width}\xD7${res.screen.height} \u2014 ${elements.length} element${elements.length === 1 ? "" : "s"} (\u2022 = tappable). Tap with tap_element({ testID | query | nativeTag }).`;
4107
+ const hidden = res.hiddenBuoy ? ` Buoy's own overlay (${res.hiddenBuoy} element${res.hiddenBuoy === 1 ? "" : "s"}) is left out \u2014 pass includeBuoy:true to see it.` : "";
4108
+ const header = `Screen ${res.screen.width}\xD7${res.screen.height} \u2014 ${elements.length} element${elements.length === 1 ? "" : "s"} (\u2022 = tappable). Tap with tap_element({ testID | query | nativeTag }).${hidden}`;
4096
4109
  return text5(`${header}
4097
4110
 
4098
4111
  ${elements.map(formatElement).join("\n")}`);
@@ -4113,6 +4126,7 @@ ${elements.map(formatElement).join("\n")}`);
4113
4126
  text: import_zod18.z.string().optional().describe("For a text input: the string to set via onChangeText."),
4114
4127
  longPress: import_zod18.z.boolean().optional().describe("Invoke the element's onLongPress instead of onPress. Fails with a clear reason if the element has no onLongPress handler."),
4115
4128
  scrollIntoView: import_zod18.z.boolean().optional().describe("Scroll the target into view first if it's off-screen. Default true."),
4129
+ includeBuoy: import_zod18.z.boolean().optional().describe("Let a fuzzy `query` match Buoy's own overlay. Default false \u2014 an exact nativeTag/testID always may."),
4116
4130
  deviceId: deviceIdInput
4117
4131
  }
4118
4132
  },
@@ -4132,7 +4146,8 @@ ${elements.map(formatElement).join("\n")}`);
4132
4146
  value: args.value,
4133
4147
  text: args.text,
4134
4148
  longPress: args.longPress,
4135
- scrollIntoView: args.scrollIntoView
4149
+ scrollIntoView: args.scrollIntoView,
4150
+ includeBuoy: args.includeBuoy
4136
4151
  },
4137
4152
  target
4138
4153
  );
@@ -4144,7 +4159,12 @@ ${elements.map(formatElement).join("\n")}`);
4144
4159
  const id = m.testID ? ` [testID=${m.testID}]` : m.nativeTag != null ? ` #${m.nativeTag}` : "";
4145
4160
  const scrolledNote = res.scrolled ? " (scrolled into view)" : "";
4146
4161
  const verb = m.via === "onValueChange" ? `Set "${label}"${id} \u2192 ${JSON.stringify(m.value)}` : m.via === "onChangeText" ? `Typed ${JSON.stringify(m.value)} into "${label}"${id}` : m.via === "onLongPress" ? `Long-pressed "${label}"${id}` : `Tapped "${label}"${id}`;
4147
- return text5(`${verb}${scrolledNote}.${flowTip}`);
4162
+ const fx = res.effect;
4163
+ const effectNote = !fx ? "" : fx.commits > 0 ? ` ${fx.commits} re-render${fx.commits === 1 ? "" : "s"} followed.` : ` No re-render followed within ${fx.observedMs}ms \u2014 the handler ran but the app did not react. The element may sit on a screen beneath the current one, or be inert; do not treat this as done.`;
4164
+ const alsoNote = res.alsoMatched?.length ? `
4165
+ Also matched equally well (the choice was a coin toss \u2014 re-tap by #nativeTag if this was wrong):
4166
+ ` + res.alsoMatched.map((c) => `- ${c.name}${c.text ? ` "${c.text}"` : ""}${c.testID ? ` [testID=${c.testID}]` : ""}${c.nativeTag != null ? ` #${c.nativeTag}` : ""}`).join("\n") : "";
4167
+ return text5(`${verb}${scrolledNote}.${effectNote}${alsoNote}${flowTip}`);
4148
4168
  }
4149
4169
  let msg = res?.reason ?? "Tap failed.";
4150
4170
  if (res?.candidates?.length) {
package/dist/index.mjs CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  registerStorageTools,
28
28
  registerZustandTools,
29
29
  runInit
30
- } from "./chunk-LS2L5OOL.mjs";
30
+ } from "./chunk-QIINQPNK.mjs";
31
31
  export {
32
32
  ALL_DEVICES,
33
33
  BROKER_PORT,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@buoy-gg/mcp",
3
3
  "mcpName": "io.github.buoy-gg/mcp",
4
- "version": "7.0.34",
4
+ "version": "7.0.36",
5
5
  "description": "MCP server for Buoy devtools — lets any LLM copilot drive Buoy tools (perf-monitor benchmarks, etc.) over the devtool sync protocol",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -32,7 +32,7 @@
32
32
  "socket.io-client": "^4.8.1",
33
33
  "zod": "^3.25.0",
34
34
  "ws": "^8.18.0",
35
- "@buoy-gg/sync-broker": "^7.0.34"
35
+ "@buoy-gg/sync-broker": "^7.0.36"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^22.0.0",