@buoy-gg/mcp 4.0.1 → 5.0.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.
package/dist/cli.mjs CHANGED
@@ -1,76 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SyncClient,
4
- createMcpServer
5
- } from "./chunk-55UIOHVS.mjs";
4
+ createMcpServer,
5
+ runInit
6
+ } from "./chunk-SQKZOREF.mjs";
6
7
 
7
8
  // src/cli.ts
8
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
-
10
- // src/init.ts
11
- import fs from "fs";
12
- import path from "path";
13
- function runInit(opts = {}) {
14
- const cwd = opts.cwd ?? process.cwd();
15
- const cliPath = opts.cliPath ?? path.resolve(__dirname, "cli.js");
16
- const skillSrcDir = opts.skillSrcDir ?? path.resolve(__dirname, "../skill");
17
- const log = opts.log ?? ((m) => process.stdout.write(m + "\n"));
18
- const entry = { type: "stdio", command: "node", args: [cliPath] };
19
- const done = [];
20
- upsertMcpConfig(path.join(cwd, ".mcp.json"), "mcpServers", entry, cwd, done);
21
- if (fs.existsSync(path.join(cwd, ".cursor"))) {
22
- upsertMcpConfig(path.join(cwd, ".cursor", "mcp.json"), "mcpServers", entry, cwd, done);
23
- }
24
- if (fs.existsSync(path.join(cwd, ".vscode"))) {
25
- upsertMcpConfig(path.join(cwd, ".vscode", "mcp.json"), "servers", entry, cwd, done);
26
- }
27
- copySkill(skillSrcDir, cwd, done);
28
- log("Buoy MCP installed:");
29
- for (const line of done) log(" \u2022 " + line);
30
- log("");
31
- log("Next steps:");
32
- log(" 1. Restart your editor (or reconnect the MCP server) to load `buoy`.");
33
- log(" 2. Open your app with Buoy devtools running on a device or simulator.");
34
- log(' 3. Say "buoy optimize" to start a guided performance pass.');
35
- }
36
- function upsertMcpConfig(file, key, entry, cwd, done) {
37
- let json = {};
38
- if (fs.existsSync(file)) {
39
- try {
40
- json = JSON.parse(fs.readFileSync(file, "utf8"));
41
- } catch {
42
- fs.copyFileSync(file, file + ".bak");
43
- done.push(`existing ${rel(file, cwd)} was invalid JSON \u2014 backed up to ${rel(file, cwd)}.bak`);
44
- json = {};
45
- }
46
- } else {
47
- fs.mkdirSync(path.dirname(file), { recursive: true });
48
- }
49
- const servers = json[key] && typeof json[key] === "object" ? json[key] : {};
50
- const existed = "buoy" in servers;
51
- servers.buoy = entry;
52
- json[key] = servers;
53
- fs.writeFileSync(file, JSON.stringify(json, null, 2) + "\n");
54
- done.push(`${existed ? "updated" : "added"} \`buoy\` in ${rel(file, cwd)}`);
55
- }
56
- function copySkill(skillSrcDir, cwd, done) {
57
- const src = path.join(skillSrcDir, "buoy-optimize", "SKILL.md");
58
- if (!fs.existsSync(src)) {
59
- done.push("\u26A0 skill source not found \u2014 skipped (skill not installed)");
60
- return;
61
- }
62
- const destDir = path.join(cwd, ".claude", "skills", "buoy-optimize");
63
- fs.mkdirSync(destDir, { recursive: true });
64
- const dest = path.join(destDir, "SKILL.md");
65
- fs.copyFileSync(src, dest);
66
- done.push(`installed the buoy-optimize skill \u2192 ${rel(dest, cwd)}`);
67
- }
68
- function rel(file, cwd) {
69
- const r = path.relative(cwd, file);
70
- return r && !r.startsWith("..") ? r : file;
71
- }
72
-
73
- // src/cli.ts
74
10
  async function main() {
75
11
  const portEnv = process.env.BUOY_BROKER_PORT;
76
12
  const sync = new SyncClient({
package/dist/index.d.mts CHANGED
@@ -120,6 +120,38 @@ declare class SyncClient {
120
120
  */
121
121
  declare function createMcpServer(sync: SyncClient): McpServer;
122
122
 
123
+ /**
124
+ * `buoy-mcp init` — wire the Buoy MCP server + the buoy-optimize skill into a
125
+ * project, so a user doesn't have to hand-edit any config.
126
+ *
127
+ * - Registers the `buoy` server in the editor MCP config(s): `.mcp.json`
128
+ * (Claude Code, always), and `.cursor/mcp.json` / `.vscode/mcp.json` when
129
+ * those editor folders already exist.
130
+ * - Copies the `buoy-optimize` skill into `.claude/skills/`.
131
+ *
132
+ * Idempotent + non-destructive: merges into existing configs (never clobbers
133
+ * other servers), and re-running just refreshes the buoy entry + skill.
134
+ *
135
+ * By default the written config launches the server via
136
+ * `npx -y @buoy-gg/mcp@latest`, so every editor restart re-resolves the newest
137
+ * published version — users can't get pinned to a stale local copy. (Passing an
138
+ * explicit `cliPath` writes a `node <path>` entry instead, for local dev/testing
139
+ * against a working build.)
140
+ */
141
+ interface InitOptions {
142
+ /** Project root to install into. @default process.cwd() */
143
+ cwd?: string;
144
+ /**
145
+ * Absolute path to a built cli.js. When set, the config launches that file
146
+ * via `node` instead of `npx @latest` — for local development only.
147
+ */
148
+ cliPath?: string;
149
+ /** Where the skill source lives. @default resolved from __dirname (../skill). */
150
+ skillSrcDir?: string;
151
+ log?: (msg: string) => void;
152
+ }
153
+ declare function runInit(opts?: InitOptions): void;
154
+
123
155
  /**
124
156
  * The generic core: tools that work for ANY Buoy tool exposing a sync adapter,
125
157
  * with zero tool-specific knowledge. Tool packs add ergonomic wrappers on top.
@@ -133,6 +165,86 @@ declare function registerGenericTools(server: McpServer, sync: SyncClient): void
133
165
  */
134
166
  declare function registerPerfMonitorTools(server: McpServer, sync: SyncClient): void;
135
167
 
168
+ /**
169
+ * The events tool pack: a compact, token-bounded view of the app's captured
170
+ * events. Drives the device's existing "Copy Settings" formatter (the heavy raw
171
+ * payloads stay on the device unless asked for), so the model gets a compact
172
+ * log by default and opts into detail when needed.
173
+ */
174
+ declare function registerEventsTools(server: McpServer, sync: SyncClient): void;
175
+
176
+ /**
177
+ * The react-query pack: a compact current-CACHE reader (the activity log is
178
+ * already covered by get_events) plus the cache-mutating actions, which reuse
179
+ * the adapter's existing handlers verbatim.
180
+ */
181
+ declare function registerReactQueryTools(server: McpServer, sync: SyncClient): void;
182
+
183
+ /**
184
+ * The zustand pack: a compact current-STATE reader (the change log is already
185
+ * covered by get_events sources:['zustand']) plus a setState action that reuses
186
+ * the adapter's existing handler.
187
+ */
188
+ declare function registerZustandTools(server: McpServer, sync: SyncClient): void;
189
+
190
+ /**
191
+ * The jotai pack: a compact current-VALUE reader (the change log is already
192
+ * covered by get_events sources:['jotai']) plus a setAtom action for writable
193
+ * atoms.
194
+ */
195
+ declare function registerJotaiTools(server: McpServer, sync: SyncClient): void;
196
+
197
+ /**
198
+ * The redux pack: a compact current-STATE reader (redux is action-based, so the
199
+ * current state isn't in the action-log snapshot — get_events sources:['redux']
200
+ * covers the action history) plus a dispatch action, both driving the live
201
+ * instrumented store.
202
+ */
203
+ declare function registerReduxTools(server: McpServer, sync: SyncClient): void;
204
+
205
+ /**
206
+ * The storage pack: a friendly, compact reader + writer over the app's
207
+ * AsyncStorage. Reuses the storage adapter's existing async.* actions; the
208
+ * device already strips Buoy's own devtool keys at the source, so only real app
209
+ * keys are returned.
210
+ */
211
+ declare function registerStorageTools(server: McpServer, sync: SyncClient): void;
212
+
213
+ /**
214
+ * The routes pack: current route + navigation stack (compact) with an optional
215
+ * sitemap, plus a navigate action — all reusing the route-events adapter's
216
+ * existing snapshot and `navigate` action.
217
+ */
218
+ declare function registerRoutesTools(server: McpServer, sync: SyncClient): void;
219
+
220
+ /**
221
+ * The console pack: a compact, token-bounded tail of the app's captured
222
+ * console.* logs, reusing the console adapter's snapshot (each entry carries a
223
+ * pre-rendered single-line `message`, so no heavy args cross into context).
224
+ */
225
+ declare function registerConsoleTools(server: McpServer, sync: SyncClient): void;
226
+
227
+ /**
228
+ * The screenshot pack: capture a tight, focused PNG of a single RN component,
229
+ * reusing the same flow the desktop app's Screenshot tool uses — the device's
230
+ * highlight-updates `locateComponent` action resolves a testID/name to a live
231
+ * on-screen rect (scrolling it into view first), and the MCP server itself
232
+ * captures + crops the iOS Simulator's framebuffer via `xcrun simctl` + `sips`
233
+ * (no desktop app required, as long as the MCP server runs on the same Mac as
234
+ * the booted Simulator).
235
+ */
236
+ declare function registerScreenshotTools(server: McpServer, sync: SyncClient): void;
237
+
238
+ /**
239
+ * A one-line update notice if a newer version is published, else null. Safe to
240
+ * await inline — bounded by the fetch timeout and short-circuited by the cache.
241
+ */
242
+ declare function getUpdateNotice(now?: number): Promise<string | null>;
243
+
244
+ declare const VERSION: string;
245
+ /** The published npm package name — used by init + the update check. */
246
+ declare const PACKAGE_NAME = "@buoy-gg/mcp";
247
+
136
248
  /** One row in an automation batch (MCP-friendly input; `id` added internally). */
137
249
  interface PerfCaseInput {
138
250
  /** Display name; becomes the saved report's metadata.name. */
@@ -376,4 +488,4 @@ declare const DASHBOARD_NAME = "Dashboard";
376
488
  /** Target token meaning "every connected device". */
377
489
  declare const ALL_DEVICES = "All";
378
490
 
379
- export { ALL_DEVICES, BROKER_PORT, BROKER_URL, type BrokerMode, DASHBOARD_NAME, DEFAULT_ACTION_TIMEOUT_MS, DEFAULT_SNAPSHOT_TIMEOUT_MS, type DeviceInfo, SyncClient, type SyncClientOptions, buildAutomationConfig, compareReportStats, createMcpServer, estimateBatchMs, formatRankingMarkdown, rankBatchFromIndex, registerGenericTools, registerPerfMonitorTools };
491
+ export { ALL_DEVICES, BROKER_PORT, BROKER_URL, type BrokerMode, DASHBOARD_NAME, DEFAULT_ACTION_TIMEOUT_MS, DEFAULT_SNAPSHOT_TIMEOUT_MS, type DeviceInfo, type InitOptions, PACKAGE_NAME, SyncClient, type SyncClientOptions, VERSION, buildAutomationConfig, compareReportStats, createMcpServer, estimateBatchMs, formatRankingMarkdown, getUpdateNotice, rankBatchFromIndex, registerConsoleTools, registerEventsTools, registerGenericTools, registerJotaiTools, registerPerfMonitorTools, registerReactQueryTools, registerReduxTools, registerRoutesTools, registerScreenshotTools, registerStorageTools, registerZustandTools, runInit };
package/dist/index.d.ts CHANGED
@@ -120,6 +120,38 @@ declare class SyncClient {
120
120
  */
121
121
  declare function createMcpServer(sync: SyncClient): McpServer;
122
122
 
123
+ /**
124
+ * `buoy-mcp init` — wire the Buoy MCP server + the buoy-optimize skill into a
125
+ * project, so a user doesn't have to hand-edit any config.
126
+ *
127
+ * - Registers the `buoy` server in the editor MCP config(s): `.mcp.json`
128
+ * (Claude Code, always), and `.cursor/mcp.json` / `.vscode/mcp.json` when
129
+ * those editor folders already exist.
130
+ * - Copies the `buoy-optimize` skill into `.claude/skills/`.
131
+ *
132
+ * Idempotent + non-destructive: merges into existing configs (never clobbers
133
+ * other servers), and re-running just refreshes the buoy entry + skill.
134
+ *
135
+ * By default the written config launches the server via
136
+ * `npx -y @buoy-gg/mcp@latest`, so every editor restart re-resolves the newest
137
+ * published version — users can't get pinned to a stale local copy. (Passing an
138
+ * explicit `cliPath` writes a `node <path>` entry instead, for local dev/testing
139
+ * against a working build.)
140
+ */
141
+ interface InitOptions {
142
+ /** Project root to install into. @default process.cwd() */
143
+ cwd?: string;
144
+ /**
145
+ * Absolute path to a built cli.js. When set, the config launches that file
146
+ * via `node` instead of `npx @latest` — for local development only.
147
+ */
148
+ cliPath?: string;
149
+ /** Where the skill source lives. @default resolved from __dirname (../skill). */
150
+ skillSrcDir?: string;
151
+ log?: (msg: string) => void;
152
+ }
153
+ declare function runInit(opts?: InitOptions): void;
154
+
123
155
  /**
124
156
  * The generic core: tools that work for ANY Buoy tool exposing a sync adapter,
125
157
  * with zero tool-specific knowledge. Tool packs add ergonomic wrappers on top.
@@ -133,6 +165,86 @@ declare function registerGenericTools(server: McpServer, sync: SyncClient): void
133
165
  */
134
166
  declare function registerPerfMonitorTools(server: McpServer, sync: SyncClient): void;
135
167
 
168
+ /**
169
+ * The events tool pack: a compact, token-bounded view of the app's captured
170
+ * events. Drives the device's existing "Copy Settings" formatter (the heavy raw
171
+ * payloads stay on the device unless asked for), so the model gets a compact
172
+ * log by default and opts into detail when needed.
173
+ */
174
+ declare function registerEventsTools(server: McpServer, sync: SyncClient): void;
175
+
176
+ /**
177
+ * The react-query pack: a compact current-CACHE reader (the activity log is
178
+ * already covered by get_events) plus the cache-mutating actions, which reuse
179
+ * the adapter's existing handlers verbatim.
180
+ */
181
+ declare function registerReactQueryTools(server: McpServer, sync: SyncClient): void;
182
+
183
+ /**
184
+ * The zustand pack: a compact current-STATE reader (the change log is already
185
+ * covered by get_events sources:['zustand']) plus a setState action that reuses
186
+ * the adapter's existing handler.
187
+ */
188
+ declare function registerZustandTools(server: McpServer, sync: SyncClient): void;
189
+
190
+ /**
191
+ * The jotai pack: a compact current-VALUE reader (the change log is already
192
+ * covered by get_events sources:['jotai']) plus a setAtom action for writable
193
+ * atoms.
194
+ */
195
+ declare function registerJotaiTools(server: McpServer, sync: SyncClient): void;
196
+
197
+ /**
198
+ * The redux pack: a compact current-STATE reader (redux is action-based, so the
199
+ * current state isn't in the action-log snapshot — get_events sources:['redux']
200
+ * covers the action history) plus a dispatch action, both driving the live
201
+ * instrumented store.
202
+ */
203
+ declare function registerReduxTools(server: McpServer, sync: SyncClient): void;
204
+
205
+ /**
206
+ * The storage pack: a friendly, compact reader + writer over the app's
207
+ * AsyncStorage. Reuses the storage adapter's existing async.* actions; the
208
+ * device already strips Buoy's own devtool keys at the source, so only real app
209
+ * keys are returned.
210
+ */
211
+ declare function registerStorageTools(server: McpServer, sync: SyncClient): void;
212
+
213
+ /**
214
+ * The routes pack: current route + navigation stack (compact) with an optional
215
+ * sitemap, plus a navigate action — all reusing the route-events adapter's
216
+ * existing snapshot and `navigate` action.
217
+ */
218
+ declare function registerRoutesTools(server: McpServer, sync: SyncClient): void;
219
+
220
+ /**
221
+ * The console pack: a compact, token-bounded tail of the app's captured
222
+ * console.* logs, reusing the console adapter's snapshot (each entry carries a
223
+ * pre-rendered single-line `message`, so no heavy args cross into context).
224
+ */
225
+ declare function registerConsoleTools(server: McpServer, sync: SyncClient): void;
226
+
227
+ /**
228
+ * The screenshot pack: capture a tight, focused PNG of a single RN component,
229
+ * reusing the same flow the desktop app's Screenshot tool uses — the device's
230
+ * highlight-updates `locateComponent` action resolves a testID/name to a live
231
+ * on-screen rect (scrolling it into view first), and the MCP server itself
232
+ * captures + crops the iOS Simulator's framebuffer via `xcrun simctl` + `sips`
233
+ * (no desktop app required, as long as the MCP server runs on the same Mac as
234
+ * the booted Simulator).
235
+ */
236
+ declare function registerScreenshotTools(server: McpServer, sync: SyncClient): void;
237
+
238
+ /**
239
+ * A one-line update notice if a newer version is published, else null. Safe to
240
+ * await inline — bounded by the fetch timeout and short-circuited by the cache.
241
+ */
242
+ declare function getUpdateNotice(now?: number): Promise<string | null>;
243
+
244
+ declare const VERSION: string;
245
+ /** The published npm package name — used by init + the update check. */
246
+ declare const PACKAGE_NAME = "@buoy-gg/mcp";
247
+
136
248
  /** One row in an automation batch (MCP-friendly input; `id` added internally). */
137
249
  interface PerfCaseInput {
138
250
  /** Display name; becomes the saved report's metadata.name. */
@@ -376,4 +488,4 @@ declare const DASHBOARD_NAME = "Dashboard";
376
488
  /** Target token meaning "every connected device". */
377
489
  declare const ALL_DEVICES = "All";
378
490
 
379
- export { ALL_DEVICES, BROKER_PORT, BROKER_URL, type BrokerMode, DASHBOARD_NAME, DEFAULT_ACTION_TIMEOUT_MS, DEFAULT_SNAPSHOT_TIMEOUT_MS, type DeviceInfo, SyncClient, type SyncClientOptions, buildAutomationConfig, compareReportStats, createMcpServer, estimateBatchMs, formatRankingMarkdown, rankBatchFromIndex, registerGenericTools, registerPerfMonitorTools };
491
+ export { ALL_DEVICES, BROKER_PORT, BROKER_URL, type BrokerMode, DASHBOARD_NAME, DEFAULT_ACTION_TIMEOUT_MS, DEFAULT_SNAPSHOT_TIMEOUT_MS, type DeviceInfo, type InitOptions, PACKAGE_NAME, SyncClient, type SyncClientOptions, VERSION, buildAutomationConfig, compareReportStats, createMcpServer, estimateBatchMs, formatRankingMarkdown, getUpdateNotice, rankBatchFromIndex, registerConsoleTools, registerEventsTools, registerGenericTools, registerJotaiTools, registerPerfMonitorTools, registerReactQueryTools, registerReduxTools, registerRoutesTools, registerScreenshotTools, registerStorageTools, registerZustandTools, runInit };