@buoy-gg/mcp 7.0.20 → 7.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-S5NQ6EUN.mjs → chunk-JQ5GZ4LG.mjs} +50 -5
- package/dist/cli.js +50 -5
- package/dist/cli.mjs +1 -1
- package/dist/index.js +50 -5
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
|
@@ -344,7 +344,7 @@ async function waitForBroker(url, attempts = 20) {
|
|
|
344
344
|
var delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
345
345
|
|
|
346
346
|
// src/version.ts
|
|
347
|
-
var VERSION = "7.0.
|
|
347
|
+
var VERSION = "7.0.21" ? "7.0.21" : "0.0.0-dev";
|
|
348
348
|
var PACKAGE_NAME = "@buoy-gg/mcp";
|
|
349
349
|
|
|
350
350
|
// src/update/checkForUpdate.ts
|
|
@@ -1254,7 +1254,7 @@ function registerEventsTools(server, sync) {
|
|
|
1254
1254
|
server.registerTool(
|
|
1255
1255
|
"get_events",
|
|
1256
1256
|
{
|
|
1257
|
-
description: "The UNIVERSAL, token-bounded activity reader for what's happening in the app across ALL Buoy tools. The events tool aggregates every source \u2014 network requests, redux/zustand/jotai actions, react-query query/mutation updates, storage writes, route changes, renders \u2014 so filter to one with `sources`: ['network'] lists HTTP requests, ['redux'] dispatched actions, ['react-query'] query updates, ['storage'] writes, ['route'] navigation. Returns a compact one-line summary per event (source \xB7 status \xB7 title \xB7 timing) by DEFAULT \u2014 not the heavy raw payloads \u2014 so it's cheap. Re-call with includeData:true, a bigger limit, or specific sources only when you need detail. PREFER this over get_snapshot (and over reading source code) for any 'what happened' / 'show me the requests/actions' question; get_snapshot is the raw heavy current-state escape hatch.",
|
|
1257
|
+
description: "The UNIVERSAL, token-bounded activity reader for what's happening in the app across ALL Buoy tools. Check this timeline BEFORE driving the UI to reproduce a bug \u2014 the failure is usually already recorded here. The events tool aggregates every source \u2014 network requests, redux/zustand/jotai actions, react-query query/mutation updates, storage writes, route changes, renders \u2014 so filter to one with `sources`: ['network'] lists HTTP requests, ['redux'] dispatched actions, ['react-query'] query updates, ['storage'] writes, ['route'] navigation. Returns a compact one-line summary per event (source \xB7 status \xB7 title \xB7 timing) by DEFAULT \u2014 not the heavy raw payloads \u2014 so it's cheap. Re-call with includeData:true, a bigger limit, or specific sources only when you need detail. PREFER this over get_snapshot (and over reading source code) for any 'what happened' / 'show me the requests/actions' question; get_snapshot is the raw heavy current-state escape hatch.",
|
|
1258
1258
|
inputSchema: {
|
|
1259
1259
|
limit: z3.number().optional().describe("Most-recent N events to include. Default 25."),
|
|
1260
1260
|
sources: z3.array(z3.string()).optional().describe('Only these sources. Coarse names accepted: "network", "redux", "react-query", "storage", "route", "render", "zustand", "jotai". Omit for all.'),
|
|
@@ -1649,7 +1649,7 @@ function registerStorageTools(server, sync) {
|
|
|
1649
1649
|
server.registerTool(
|
|
1650
1650
|
"get_storage",
|
|
1651
1651
|
{
|
|
1652
|
-
description: "Read the app's storage keys across ALL backends: AsyncStorage, MMKV (per instance), and Expo SecureStore. Compact by DEFAULT \u2014 keys only \u2014 so it's token-cheap; pass includeValues:true for the values (truncated), or a `pattern` substring to narrow. Buoy's own internal keys are already filtered out.
|
|
1652
|
+
description: "Read the app's storage keys across ALL backends: AsyncStorage, MMKV (per instance), and Expo SecureStore. Data wrong or missing after an app restart \u2192 read the persisted values here FIRST \u2014 the bug is usually a stale, missing, or malformed stored value, and reading it beats hunting for it in code. Compact by DEFAULT \u2014 keys only \u2014 so it's token-cheap; pass includeValues:true for the values (truncated), or a `pattern` substring to narrow. Buoy's own internal keys are already filtered out.",
|
|
1653
1653
|
inputSchema: {
|
|
1654
1654
|
pattern: z8.string().optional().describe("Only keys containing this substring (case-insensitive)."),
|
|
1655
1655
|
includeValues: z8.boolean().optional().describe("Include each key's value (truncated). Default false (keys only)."),
|
|
@@ -1850,7 +1850,7 @@ function registerConsoleTools(server, sync) {
|
|
|
1850
1850
|
server.registerTool(
|
|
1851
1851
|
"get_console",
|
|
1852
1852
|
{
|
|
1853
|
-
description: "Read the app's captured console logs (console.log/warn/error/\u2026) as a compact tail \u2014 time \xB7 level \xB7 message. Token-cheap (uses each entry's pre-rendered message, not raw args). Filter by minimum level (e.g. level:'warning' for warnings+errors) or a message substring.
|
|
1853
|
+
description: "Read the app's captured console logs (console.log/warn/error/\u2026) as a compact tail \u2014 time \xB7 level \xB7 message. App crashing or erroring \u2192 read this FIRST: it captures crashes and errors including FATAL uncaught JS errors (tagged [FATAL], hooked from RN's global error handler), so a dead app's last words are here, not in the code. Token-cheap (uses each entry's pre-rendered message, not raw args). Filter by minimum level (e.g. level:'warning' for warnings+errors) or a message substring. For full args/stack of an entry, fall back to get_snapshot('console').",
|
|
1854
1854
|
inputSchema: {
|
|
1855
1855
|
level: z10.enum(["verbose", "info", "warning", "error"]).optional().describe("Minimum level to include (severity threshold). e.g. 'warning' = warnings + errors. Default all."),
|
|
1856
1856
|
limit: z10.number().optional().describe("Most-recent N entries. Default 50."),
|
|
@@ -2192,7 +2192,7 @@ function registerNetworkTools(server, sync) {
|
|
|
2192
2192
|
server.registerTool(
|
|
2193
2193
|
"get_network_requests",
|
|
2194
2194
|
{
|
|
2195
|
-
description: "List captured HTTP requests WITH their request ids, plus which ones are pinned/saved. Use this (not get_events) when you need to ACT on a request \u2014 every network action is keyed by the id, and get_events does not emit ids. Compact by default: one line per request (id \xB7 status \xB7 method \xB7 path \xB7 timing \xB7 size). Set flagged:'pinned'|'saved'|'any' to read the developer's KEPT requests \u2014 those are snapshots that outlive Clear, the 500-request cap and app restarts, so treat a pinned request as 'a human flagged this as the problem'. Filter with status:'errors' to go straight to failures, or `pattern` to match a URL substring. includeBodies:true adds truncated request/response payloads (heavier).",
|
|
2195
|
+
description: "List captured HTTP requests WITH their request ids, plus which ones are pinned/saved. API data wrong or calls failing \u2192 read the actual request+response bodies here instead of guessing from code; capture starts at app launch, so boot-time requests (session bootstrap, first queries) are included. Use this (not get_events) when you need to ACT on a request \u2014 every network action is keyed by the id, and get_events does not emit ids. Compact by default: one line per request (id \xB7 status \xB7 method \xB7 path \xB7 timing \xB7 size). Set flagged:'pinned'|'saved'|'any' to read the developer's KEPT requests \u2014 those are snapshots that outlive Clear, the 500-request cap and app restarts, so treat a pinned request as 'a human flagged this as the problem'. Filter with status:'errors' to go straight to failures, or `pattern` to match a URL substring. includeBodies:true adds truncated request/response payloads (heavier).",
|
|
2196
2196
|
inputSchema: {
|
|
2197
2197
|
limit: z12.number().optional().describe("Most-recent N requests. Default 25."),
|
|
2198
2198
|
pattern: z12.string().optional().describe("Only requests whose URL contains this substring (case-insensitive)."),
|
|
@@ -3659,6 +3659,8 @@ function runInit(opts = {}) {
|
|
|
3659
3659
|
upsertMcpConfig(path3.join(cwd, ".vscode", "mcp.json"), "servers", entry, cwd, done);
|
|
3660
3660
|
}
|
|
3661
3661
|
installSkills(skillSrcDir, cwd, done);
|
|
3662
|
+
appendDebuggingGuide(path3.join(cwd, "CLAUDE.md"), cwd, done);
|
|
3663
|
+
appendDebuggingGuide(path3.join(cwd, "AGENTS.md"), cwd, done);
|
|
3662
3664
|
log("Buoy MCP installed:");
|
|
3663
3665
|
for (const line of done) log(" \u2022 " + line);
|
|
3664
3666
|
log("");
|
|
@@ -3805,6 +3807,49 @@ function upsertMcpConfig(file, key, entry, cwd, done) {
|
|
|
3805
3807
|
fs3.writeFileSync(file, JSON.stringify(json3, null, 2) + "\n");
|
|
3806
3808
|
done.push(`${existed ? "updated" : "added"} \`buoy\` in ${rel(file, cwd)}`);
|
|
3807
3809
|
}
|
|
3810
|
+
var GUIDE_HEADING = "# Debugging with Buoy";
|
|
3811
|
+
var DEBUGGING_GUIDE = `${GUIDE_HEADING}
|
|
3812
|
+
|
|
3813
|
+
This app's runtime is inspectable while it runs: the Buoy MCP tools read live
|
|
3814
|
+
state straight from the device. Route by symptom before reading source:
|
|
3815
|
+
|
|
3816
|
+
- \`get_events\` \u2014 the universal activity timeline (network, state changes,
|
|
3817
|
+
storage writes, routes, renders). Check it BEFORE driving the UI to
|
|
3818
|
+
reproduce a bug \u2014 the failure is usually already recorded.
|
|
3819
|
+
- \`get_network_requests\` \u2014 API data wrong or calls failing \u2192 read the actual
|
|
3820
|
+
request + response bodies instead of guessing from code. Boot-time requests
|
|
3821
|
+
are captured too.
|
|
3822
|
+
- \`get_console\` \u2014 crashes and errors, including FATAL uncaught JS errors
|
|
3823
|
+
(tagged \`[FATAL]\`).
|
|
3824
|
+
- \`get_storage\` \u2014 data wrong or missing after an app restart \u2192 read the
|
|
3825
|
+
persisted values FIRST.
|
|
3826
|
+
- \`get_snapshot\` \u2014 full current state of any one tool when the compact views
|
|
3827
|
+
aren't enough.
|
|
3828
|
+
|
|
3829
|
+
Runtime facts beat guesses.
|
|
3830
|
+
`;
|
|
3831
|
+
function appendDebuggingGuide(file, cwd, done) {
|
|
3832
|
+
let existing = "";
|
|
3833
|
+
if (fs3.existsSync(file)) {
|
|
3834
|
+
try {
|
|
3835
|
+
existing = fs3.readFileSync(file, "utf8");
|
|
3836
|
+
} catch {
|
|
3837
|
+
done.push(`\u26A0 could not read ${rel(file, cwd)} \u2014 skipped the debugging guide`);
|
|
3838
|
+
return;
|
|
3839
|
+
}
|
|
3840
|
+
if (existing.includes(GUIDE_HEADING)) {
|
|
3841
|
+
done.push(`${rel(file, cwd)} already has the "${GUIDE_HEADING}" block`);
|
|
3842
|
+
return;
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
const separator = existing === "" ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
|
|
3846
|
+
try {
|
|
3847
|
+
fs3.writeFileSync(file, existing + separator + DEBUGGING_GUIDE);
|
|
3848
|
+
done.push(`${existing ? "appended" : "created"} "${GUIDE_HEADING}" block in ${rel(file, cwd)}`);
|
|
3849
|
+
} catch {
|
|
3850
|
+
done.push(`\u26A0 could not write ${rel(file, cwd)} \u2014 skipped the debugging guide`);
|
|
3851
|
+
}
|
|
3852
|
+
}
|
|
3808
3853
|
function installSkills(skillSrcDir, cwd, done) {
|
|
3809
3854
|
if (!fs3.existsSync(skillSrcDir)) {
|
|
3810
3855
|
done.push("\u26A0 no bundled skills found \u2014 skipped");
|
package/dist/cli.js
CHANGED
|
@@ -384,7 +384,7 @@ var import_node_os = __toESM(require("os"));
|
|
|
384
384
|
var import_node_path = __toESM(require("path"));
|
|
385
385
|
|
|
386
386
|
// src/version.ts
|
|
387
|
-
var VERSION = "7.0.
|
|
387
|
+
var VERSION = "7.0.21" ? "7.0.21" : "0.0.0-dev";
|
|
388
388
|
var PACKAGE_NAME = "@buoy-gg/mcp";
|
|
389
389
|
|
|
390
390
|
// src/update/checkForUpdate.ts
|
|
@@ -1290,7 +1290,7 @@ function registerEventsTools(server, sync) {
|
|
|
1290
1290
|
server.registerTool(
|
|
1291
1291
|
"get_events",
|
|
1292
1292
|
{
|
|
1293
|
-
description: "The UNIVERSAL, token-bounded activity reader for what's happening in the app across ALL Buoy tools. The events tool aggregates every source \u2014 network requests, redux/zustand/jotai actions, react-query query/mutation updates, storage writes, route changes, renders \u2014 so filter to one with `sources`: ['network'] lists HTTP requests, ['redux'] dispatched actions, ['react-query'] query updates, ['storage'] writes, ['route'] navigation. Returns a compact one-line summary per event (source \xB7 status \xB7 title \xB7 timing) by DEFAULT \u2014 not the heavy raw payloads \u2014 so it's cheap. Re-call with includeData:true, a bigger limit, or specific sources only when you need detail. PREFER this over get_snapshot (and over reading source code) for any 'what happened' / 'show me the requests/actions' question; get_snapshot is the raw heavy current-state escape hatch.",
|
|
1293
|
+
description: "The UNIVERSAL, token-bounded activity reader for what's happening in the app across ALL Buoy tools. Check this timeline BEFORE driving the UI to reproduce a bug \u2014 the failure is usually already recorded here. The events tool aggregates every source \u2014 network requests, redux/zustand/jotai actions, react-query query/mutation updates, storage writes, route changes, renders \u2014 so filter to one with `sources`: ['network'] lists HTTP requests, ['redux'] dispatched actions, ['react-query'] query updates, ['storage'] writes, ['route'] navigation. Returns a compact one-line summary per event (source \xB7 status \xB7 title \xB7 timing) by DEFAULT \u2014 not the heavy raw payloads \u2014 so it's cheap. Re-call with includeData:true, a bigger limit, or specific sources only when you need detail. PREFER this over get_snapshot (and over reading source code) for any 'what happened' / 'show me the requests/actions' question; get_snapshot is the raw heavy current-state escape hatch.",
|
|
1294
1294
|
inputSchema: {
|
|
1295
1295
|
limit: import_zod3.z.number().optional().describe("Most-recent N events to include. Default 25."),
|
|
1296
1296
|
sources: import_zod3.z.array(import_zod3.z.string()).optional().describe('Only these sources. Coarse names accepted: "network", "redux", "react-query", "storage", "route", "render", "zustand", "jotai". Omit for all.'),
|
|
@@ -1455,7 +1455,7 @@ function registerNetworkTools(server, sync) {
|
|
|
1455
1455
|
server.registerTool(
|
|
1456
1456
|
"get_network_requests",
|
|
1457
1457
|
{
|
|
1458
|
-
description: "List captured HTTP requests WITH their request ids, plus which ones are pinned/saved. Use this (not get_events) when you need to ACT on a request \u2014 every network action is keyed by the id, and get_events does not emit ids. Compact by default: one line per request (id \xB7 status \xB7 method \xB7 path \xB7 timing \xB7 size). Set flagged:'pinned'|'saved'|'any' to read the developer's KEPT requests \u2014 those are snapshots that outlive Clear, the 500-request cap and app restarts, so treat a pinned request as 'a human flagged this as the problem'. Filter with status:'errors' to go straight to failures, or `pattern` to match a URL substring. includeBodies:true adds truncated request/response payloads (heavier).",
|
|
1458
|
+
description: "List captured HTTP requests WITH their request ids, plus which ones are pinned/saved. API data wrong or calls failing \u2192 read the actual request+response bodies here instead of guessing from code; capture starts at app launch, so boot-time requests (session bootstrap, first queries) are included. Use this (not get_events) when you need to ACT on a request \u2014 every network action is keyed by the id, and get_events does not emit ids. Compact by default: one line per request (id \xB7 status \xB7 method \xB7 path \xB7 timing \xB7 size). Set flagged:'pinned'|'saved'|'any' to read the developer's KEPT requests \u2014 those are snapshots that outlive Clear, the 500-request cap and app restarts, so treat a pinned request as 'a human flagged this as the problem'. Filter with status:'errors' to go straight to failures, or `pattern` to match a URL substring. includeBodies:true adds truncated request/response payloads (heavier).",
|
|
1459
1459
|
inputSchema: {
|
|
1460
1460
|
limit: import_zod4.z.number().optional().describe("Most-recent N requests. Default 25."),
|
|
1461
1461
|
pattern: import_zod4.z.string().optional().describe("Only requests whose URL contains this substring (case-insensitive)."),
|
|
@@ -2172,7 +2172,7 @@ function registerStorageTools(server, sync) {
|
|
|
2172
2172
|
server.registerTool(
|
|
2173
2173
|
"get_storage",
|
|
2174
2174
|
{
|
|
2175
|
-
description: "Read the app's storage keys across ALL backends: AsyncStorage, MMKV (per instance), and Expo SecureStore. Compact by DEFAULT \u2014 keys only \u2014 so it's token-cheap; pass includeValues:true for the values (truncated), or a `pattern` substring to narrow. Buoy's own internal keys are already filtered out.
|
|
2175
|
+
description: "Read the app's storage keys across ALL backends: AsyncStorage, MMKV (per instance), and Expo SecureStore. Data wrong or missing after an app restart \u2192 read the persisted values here FIRST \u2014 the bug is usually a stale, missing, or malformed stored value, and reading it beats hunting for it in code. Compact by DEFAULT \u2014 keys only \u2014 so it's token-cheap; pass includeValues:true for the values (truncated), or a `pattern` substring to narrow. Buoy's own internal keys are already filtered out.",
|
|
2176
2176
|
inputSchema: {
|
|
2177
2177
|
pattern: import_zod9.z.string().optional().describe("Only keys containing this substring (case-insensitive)."),
|
|
2178
2178
|
includeValues: import_zod9.z.boolean().optional().describe("Include each key's value (truncated). Default false (keys only)."),
|
|
@@ -2373,7 +2373,7 @@ function registerConsoleTools(server, sync) {
|
|
|
2373
2373
|
server.registerTool(
|
|
2374
2374
|
"get_console",
|
|
2375
2375
|
{
|
|
2376
|
-
description: "Read the app's captured console logs (console.log/warn/error/\u2026) as a compact tail \u2014 time \xB7 level \xB7 message. Token-cheap (uses each entry's pre-rendered message, not raw args). Filter by minimum level (e.g. level:'warning' for warnings+errors) or a message substring.
|
|
2376
|
+
description: "Read the app's captured console logs (console.log/warn/error/\u2026) as a compact tail \u2014 time \xB7 level \xB7 message. App crashing or erroring \u2192 read this FIRST: it captures crashes and errors including FATAL uncaught JS errors (tagged [FATAL], hooked from RN's global error handler), so a dead app's last words are here, not in the code. Token-cheap (uses each entry's pre-rendered message, not raw args). Filter by minimum level (e.g. level:'warning' for warnings+errors) or a message substring. For full args/stack of an entry, fall back to get_snapshot('console').",
|
|
2377
2377
|
inputSchema: {
|
|
2378
2378
|
level: import_zod11.z.enum(["verbose", "info", "warning", "error"]).optional().describe("Minimum level to include (severity threshold). e.g. 'warning' = warnings + errors. Default all."),
|
|
2379
2379
|
limit: import_zod11.z.number().optional().describe("Most-recent N entries. Default 50."),
|
|
@@ -3691,6 +3691,8 @@ function runInit(opts = {}) {
|
|
|
3691
3691
|
upsertMcpConfig(import_node_path3.default.join(cwd, ".vscode", "mcp.json"), "servers", entry, cwd, done);
|
|
3692
3692
|
}
|
|
3693
3693
|
installSkills(skillSrcDir, cwd, done);
|
|
3694
|
+
appendDebuggingGuide(import_node_path3.default.join(cwd, "CLAUDE.md"), cwd, done);
|
|
3695
|
+
appendDebuggingGuide(import_node_path3.default.join(cwd, "AGENTS.md"), cwd, done);
|
|
3694
3696
|
log("Buoy MCP installed:");
|
|
3695
3697
|
for (const line of done) log(" \u2022 " + line);
|
|
3696
3698
|
log("");
|
|
@@ -3837,6 +3839,49 @@ function upsertMcpConfig(file, key, entry, cwd, done) {
|
|
|
3837
3839
|
import_node_fs3.default.writeFileSync(file, JSON.stringify(json3, null, 2) + "\n");
|
|
3838
3840
|
done.push(`${existed ? "updated" : "added"} \`buoy\` in ${rel(file, cwd)}`);
|
|
3839
3841
|
}
|
|
3842
|
+
var GUIDE_HEADING = "# Debugging with Buoy";
|
|
3843
|
+
var DEBUGGING_GUIDE = `${GUIDE_HEADING}
|
|
3844
|
+
|
|
3845
|
+
This app's runtime is inspectable while it runs: the Buoy MCP tools read live
|
|
3846
|
+
state straight from the device. Route by symptom before reading source:
|
|
3847
|
+
|
|
3848
|
+
- \`get_events\` \u2014 the universal activity timeline (network, state changes,
|
|
3849
|
+
storage writes, routes, renders). Check it BEFORE driving the UI to
|
|
3850
|
+
reproduce a bug \u2014 the failure is usually already recorded.
|
|
3851
|
+
- \`get_network_requests\` \u2014 API data wrong or calls failing \u2192 read the actual
|
|
3852
|
+
request + response bodies instead of guessing from code. Boot-time requests
|
|
3853
|
+
are captured too.
|
|
3854
|
+
- \`get_console\` \u2014 crashes and errors, including FATAL uncaught JS errors
|
|
3855
|
+
(tagged \`[FATAL]\`).
|
|
3856
|
+
- \`get_storage\` \u2014 data wrong or missing after an app restart \u2192 read the
|
|
3857
|
+
persisted values FIRST.
|
|
3858
|
+
- \`get_snapshot\` \u2014 full current state of any one tool when the compact views
|
|
3859
|
+
aren't enough.
|
|
3860
|
+
|
|
3861
|
+
Runtime facts beat guesses.
|
|
3862
|
+
`;
|
|
3863
|
+
function appendDebuggingGuide(file, cwd, done) {
|
|
3864
|
+
let existing = "";
|
|
3865
|
+
if (import_node_fs3.default.existsSync(file)) {
|
|
3866
|
+
try {
|
|
3867
|
+
existing = import_node_fs3.default.readFileSync(file, "utf8");
|
|
3868
|
+
} catch {
|
|
3869
|
+
done.push(`\u26A0 could not read ${rel(file, cwd)} \u2014 skipped the debugging guide`);
|
|
3870
|
+
return;
|
|
3871
|
+
}
|
|
3872
|
+
if (existing.includes(GUIDE_HEADING)) {
|
|
3873
|
+
done.push(`${rel(file, cwd)} already has the "${GUIDE_HEADING}" block`);
|
|
3874
|
+
return;
|
|
3875
|
+
}
|
|
3876
|
+
}
|
|
3877
|
+
const separator = existing === "" ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
|
|
3878
|
+
try {
|
|
3879
|
+
import_node_fs3.default.writeFileSync(file, existing + separator + DEBUGGING_GUIDE);
|
|
3880
|
+
done.push(`${existing ? "appended" : "created"} "${GUIDE_HEADING}" block in ${rel(file, cwd)}`);
|
|
3881
|
+
} catch {
|
|
3882
|
+
done.push(`\u26A0 could not write ${rel(file, cwd)} \u2014 skipped the debugging guide`);
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3840
3885
|
function installSkills(skillSrcDir, cwd, done) {
|
|
3841
3886
|
if (!import_node_fs3.default.existsSync(skillSrcDir)) {
|
|
3842
3887
|
done.push("\u26A0 no bundled skills found \u2014 skipped");
|
package/dist/cli.mjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -419,7 +419,7 @@ var import_node_os = __toESM(require("os"));
|
|
|
419
419
|
var import_node_path = __toESM(require("path"));
|
|
420
420
|
|
|
421
421
|
// src/version.ts
|
|
422
|
-
var VERSION = "7.0.
|
|
422
|
+
var VERSION = "7.0.21" ? "7.0.21" : "0.0.0-dev";
|
|
423
423
|
var PACKAGE_NAME = "@buoy-gg/mcp";
|
|
424
424
|
|
|
425
425
|
// src/update/checkForUpdate.ts
|
|
@@ -1325,7 +1325,7 @@ function registerEventsTools(server, sync) {
|
|
|
1325
1325
|
server.registerTool(
|
|
1326
1326
|
"get_events",
|
|
1327
1327
|
{
|
|
1328
|
-
description: "The UNIVERSAL, token-bounded activity reader for what's happening in the app across ALL Buoy tools. The events tool aggregates every source \u2014 network requests, redux/zustand/jotai actions, react-query query/mutation updates, storage writes, route changes, renders \u2014 so filter to one with `sources`: ['network'] lists HTTP requests, ['redux'] dispatched actions, ['react-query'] query updates, ['storage'] writes, ['route'] navigation. Returns a compact one-line summary per event (source \xB7 status \xB7 title \xB7 timing) by DEFAULT \u2014 not the heavy raw payloads \u2014 so it's cheap. Re-call with includeData:true, a bigger limit, or specific sources only when you need detail. PREFER this over get_snapshot (and over reading source code) for any 'what happened' / 'show me the requests/actions' question; get_snapshot is the raw heavy current-state escape hatch.",
|
|
1328
|
+
description: "The UNIVERSAL, token-bounded activity reader for what's happening in the app across ALL Buoy tools. Check this timeline BEFORE driving the UI to reproduce a bug \u2014 the failure is usually already recorded here. The events tool aggregates every source \u2014 network requests, redux/zustand/jotai actions, react-query query/mutation updates, storage writes, route changes, renders \u2014 so filter to one with `sources`: ['network'] lists HTTP requests, ['redux'] dispatched actions, ['react-query'] query updates, ['storage'] writes, ['route'] navigation. Returns a compact one-line summary per event (source \xB7 status \xB7 title \xB7 timing) by DEFAULT \u2014 not the heavy raw payloads \u2014 so it's cheap. Re-call with includeData:true, a bigger limit, or specific sources only when you need detail. PREFER this over get_snapshot (and over reading source code) for any 'what happened' / 'show me the requests/actions' question; get_snapshot is the raw heavy current-state escape hatch.",
|
|
1329
1329
|
inputSchema: {
|
|
1330
1330
|
limit: import_zod3.z.number().optional().describe("Most-recent N events to include. Default 25."),
|
|
1331
1331
|
sources: import_zod3.z.array(import_zod3.z.string()).optional().describe('Only these sources. Coarse names accepted: "network", "redux", "react-query", "storage", "route", "render", "zustand", "jotai". Omit for all.'),
|
|
@@ -1490,7 +1490,7 @@ function registerNetworkTools(server, sync) {
|
|
|
1490
1490
|
server.registerTool(
|
|
1491
1491
|
"get_network_requests",
|
|
1492
1492
|
{
|
|
1493
|
-
description: "List captured HTTP requests WITH their request ids, plus which ones are pinned/saved. Use this (not get_events) when you need to ACT on a request \u2014 every network action is keyed by the id, and get_events does not emit ids. Compact by default: one line per request (id \xB7 status \xB7 method \xB7 path \xB7 timing \xB7 size). Set flagged:'pinned'|'saved'|'any' to read the developer's KEPT requests \u2014 those are snapshots that outlive Clear, the 500-request cap and app restarts, so treat a pinned request as 'a human flagged this as the problem'. Filter with status:'errors' to go straight to failures, or `pattern` to match a URL substring. includeBodies:true adds truncated request/response payloads (heavier).",
|
|
1493
|
+
description: "List captured HTTP requests WITH their request ids, plus which ones are pinned/saved. API data wrong or calls failing \u2192 read the actual request+response bodies here instead of guessing from code; capture starts at app launch, so boot-time requests (session bootstrap, first queries) are included. Use this (not get_events) when you need to ACT on a request \u2014 every network action is keyed by the id, and get_events does not emit ids. Compact by default: one line per request (id \xB7 status \xB7 method \xB7 path \xB7 timing \xB7 size). Set flagged:'pinned'|'saved'|'any' to read the developer's KEPT requests \u2014 those are snapshots that outlive Clear, the 500-request cap and app restarts, so treat a pinned request as 'a human flagged this as the problem'. Filter with status:'errors' to go straight to failures, or `pattern` to match a URL substring. includeBodies:true adds truncated request/response payloads (heavier).",
|
|
1494
1494
|
inputSchema: {
|
|
1495
1495
|
limit: import_zod4.z.number().optional().describe("Most-recent N requests. Default 25."),
|
|
1496
1496
|
pattern: import_zod4.z.string().optional().describe("Only requests whose URL contains this substring (case-insensitive)."),
|
|
@@ -2207,7 +2207,7 @@ function registerStorageTools(server, sync) {
|
|
|
2207
2207
|
server.registerTool(
|
|
2208
2208
|
"get_storage",
|
|
2209
2209
|
{
|
|
2210
|
-
description: "Read the app's storage keys across ALL backends: AsyncStorage, MMKV (per instance), and Expo SecureStore. Compact by DEFAULT \u2014 keys only \u2014 so it's token-cheap; pass includeValues:true for the values (truncated), or a `pattern` substring to narrow. Buoy's own internal keys are already filtered out.
|
|
2210
|
+
description: "Read the app's storage keys across ALL backends: AsyncStorage, MMKV (per instance), and Expo SecureStore. Data wrong or missing after an app restart \u2192 read the persisted values here FIRST \u2014 the bug is usually a stale, missing, or malformed stored value, and reading it beats hunting for it in code. Compact by DEFAULT \u2014 keys only \u2014 so it's token-cheap; pass includeValues:true for the values (truncated), or a `pattern` substring to narrow. Buoy's own internal keys are already filtered out.",
|
|
2211
2211
|
inputSchema: {
|
|
2212
2212
|
pattern: import_zod9.z.string().optional().describe("Only keys containing this substring (case-insensitive)."),
|
|
2213
2213
|
includeValues: import_zod9.z.boolean().optional().describe("Include each key's value (truncated). Default false (keys only)."),
|
|
@@ -2408,7 +2408,7 @@ function registerConsoleTools(server, sync) {
|
|
|
2408
2408
|
server.registerTool(
|
|
2409
2409
|
"get_console",
|
|
2410
2410
|
{
|
|
2411
|
-
description: "Read the app's captured console logs (console.log/warn/error/\u2026) as a compact tail \u2014 time \xB7 level \xB7 message. Token-cheap (uses each entry's pre-rendered message, not raw args). Filter by minimum level (e.g. level:'warning' for warnings+errors) or a message substring.
|
|
2411
|
+
description: "Read the app's captured console logs (console.log/warn/error/\u2026) as a compact tail \u2014 time \xB7 level \xB7 message. App crashing or erroring \u2192 read this FIRST: it captures crashes and errors including FATAL uncaught JS errors (tagged [FATAL], hooked from RN's global error handler), so a dead app's last words are here, not in the code. Token-cheap (uses each entry's pre-rendered message, not raw args). Filter by minimum level (e.g. level:'warning' for warnings+errors) or a message substring. For full args/stack of an entry, fall back to get_snapshot('console').",
|
|
2412
2412
|
inputSchema: {
|
|
2413
2413
|
level: import_zod11.z.enum(["verbose", "info", "warning", "error"]).optional().describe("Minimum level to include (severity threshold). e.g. 'warning' = warnings + errors. Default all."),
|
|
2414
2414
|
limit: import_zod11.z.number().optional().describe("Most-recent N entries. Default 50."),
|
|
@@ -3726,6 +3726,8 @@ function runInit(opts = {}) {
|
|
|
3726
3726
|
upsertMcpConfig(import_node_path3.default.join(cwd, ".vscode", "mcp.json"), "servers", entry, cwd, done);
|
|
3727
3727
|
}
|
|
3728
3728
|
installSkills(skillSrcDir, cwd, done);
|
|
3729
|
+
appendDebuggingGuide(import_node_path3.default.join(cwd, "CLAUDE.md"), cwd, done);
|
|
3730
|
+
appendDebuggingGuide(import_node_path3.default.join(cwd, "AGENTS.md"), cwd, done);
|
|
3729
3731
|
log("Buoy MCP installed:");
|
|
3730
3732
|
for (const line of done) log(" \u2022 " + line);
|
|
3731
3733
|
log("");
|
|
@@ -3872,6 +3874,49 @@ function upsertMcpConfig(file, key, entry, cwd, done) {
|
|
|
3872
3874
|
import_node_fs3.default.writeFileSync(file, JSON.stringify(json3, null, 2) + "\n");
|
|
3873
3875
|
done.push(`${existed ? "updated" : "added"} \`buoy\` in ${rel(file, cwd)}`);
|
|
3874
3876
|
}
|
|
3877
|
+
var GUIDE_HEADING = "# Debugging with Buoy";
|
|
3878
|
+
var DEBUGGING_GUIDE = `${GUIDE_HEADING}
|
|
3879
|
+
|
|
3880
|
+
This app's runtime is inspectable while it runs: the Buoy MCP tools read live
|
|
3881
|
+
state straight from the device. Route by symptom before reading source:
|
|
3882
|
+
|
|
3883
|
+
- \`get_events\` \u2014 the universal activity timeline (network, state changes,
|
|
3884
|
+
storage writes, routes, renders). Check it BEFORE driving the UI to
|
|
3885
|
+
reproduce a bug \u2014 the failure is usually already recorded.
|
|
3886
|
+
- \`get_network_requests\` \u2014 API data wrong or calls failing \u2192 read the actual
|
|
3887
|
+
request + response bodies instead of guessing from code. Boot-time requests
|
|
3888
|
+
are captured too.
|
|
3889
|
+
- \`get_console\` \u2014 crashes and errors, including FATAL uncaught JS errors
|
|
3890
|
+
(tagged \`[FATAL]\`).
|
|
3891
|
+
- \`get_storage\` \u2014 data wrong or missing after an app restart \u2192 read the
|
|
3892
|
+
persisted values FIRST.
|
|
3893
|
+
- \`get_snapshot\` \u2014 full current state of any one tool when the compact views
|
|
3894
|
+
aren't enough.
|
|
3895
|
+
|
|
3896
|
+
Runtime facts beat guesses.
|
|
3897
|
+
`;
|
|
3898
|
+
function appendDebuggingGuide(file, cwd, done) {
|
|
3899
|
+
let existing = "";
|
|
3900
|
+
if (import_node_fs3.default.existsSync(file)) {
|
|
3901
|
+
try {
|
|
3902
|
+
existing = import_node_fs3.default.readFileSync(file, "utf8");
|
|
3903
|
+
} catch {
|
|
3904
|
+
done.push(`\u26A0 could not read ${rel(file, cwd)} \u2014 skipped the debugging guide`);
|
|
3905
|
+
return;
|
|
3906
|
+
}
|
|
3907
|
+
if (existing.includes(GUIDE_HEADING)) {
|
|
3908
|
+
done.push(`${rel(file, cwd)} already has the "${GUIDE_HEADING}" block`);
|
|
3909
|
+
return;
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
const separator = existing === "" ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
|
|
3913
|
+
try {
|
|
3914
|
+
import_node_fs3.default.writeFileSync(file, existing + separator + DEBUGGING_GUIDE);
|
|
3915
|
+
done.push(`${existing ? "appended" : "created"} "${GUIDE_HEADING}" block in ${rel(file, cwd)}`);
|
|
3916
|
+
} catch {
|
|
3917
|
+
done.push(`\u26A0 could not write ${rel(file, cwd)} \u2014 skipped the debugging guide`);
|
|
3918
|
+
}
|
|
3919
|
+
}
|
|
3875
3920
|
function installSkills(skillSrcDir, cwd, done) {
|
|
3876
3921
|
if (!import_node_fs3.default.existsSync(skillSrcDir)) {
|
|
3877
3922
|
done.push("\u26A0 no bundled skills found \u2014 skipped");
|
package/dist/index.mjs
CHANGED
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.
|
|
4
|
+
"version": "7.0.21",
|
|
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",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
32
32
|
"socket.io-client": "^4.8.1",
|
|
33
33
|
"zod": "^3.25.0",
|
|
34
|
-
"@buoy-gg/sync-broker": "^7.0.
|
|
34
|
+
"@buoy-gg/sync-broker": "^7.0.21"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "^22.0.0",
|