Drive your Buoy dev tools from an AI coding assistant. The Buoy MCP server lets Claude Code, Cursor, and other MCP clients read your app's live runtime — network requests, state (Redux/Zustand/Jotai), React Query, storage, routes, console — and take actions, run performance benchmarks, drive the UI by tapping through it, and even screenshot a specific on-screen component, all against your running app.
One command wires the server into your editor and installs the Buoy skill:
npx -y @buoy-gg/mcp@latest init
npx -y @buoy-gg/mcp@latest init
This merges a buoy server into your MCP config (.mcp.json for Claude Code, plus .cursor/mcp.json and .vscode/mcp.json when those folders exist) and drops the buoy-optimize skill into .claude/skills/. It's non-destructive — existing servers are preserved, and re-running just refreshes the Buoy entry.
Then restart your editor (or reconnect the MCP server) and open your app with Buoy devtools running.
The config it writes launches the server via npx -y @buoy-gg/mcp@latest, so every editor restart re-resolves the newest published version — you don't get pinned to a stale copy.
Because the default config uses @latest, you're normally always current. To force a refresh (or update the installed skill), re-run:
npx -y @buoy-gg/mcp@latest init
npx -y @buoy-gg/mcp@latest init
The server also checks npm about once a day and, when a newer version is out, includes a one-line notice in the list_devices result so your assistant can prompt you to update.
If you'd rather wire it by hand, add this to your MCP config:
{
"mcpServers": {
"buoy": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@buoy-gg/mcp@latest"]
}
}
}
{
"mcpServers": {
"buoy": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@buoy-gg/mcp@latest"]
}
}
}
Ask your assistant to start with list_devices to see connected devices and the tools each exposes. From there it can:
A good starting prompt: "buoy optimize" kicks off a guided performance pass using the bundled skill.
Two tools let your agent operate the app the way a user would — without screenshots or pixel coordinates, so it's fast and works on physical devices too:
A typical loop is: describe_screen to see the options → tap_element({ testID }) to act → describe_screen again to confirm the result. Prefer testID or nativeTag when a screen has repeated labels.
init also installs a buoy-optimize skill — a guided wizard that automates mobile performance work end to end. Whether you're shipping a new feature or fixing a screen that's janky on device, your assistant benchmarks implementation variants on the real device with Bench, reads the ranked results, applies the winning change, and repeats until the metrics plateau.
Measuring on-device instead of guessing is what makes it fast: optimization passes that used to take days or weeks of AI back-and-forth finish in minutes. One real run took a Skia LED display from 28 lights stuttering to over 12,000 lights with no lag.
It's close to fully automated — the parts that stay manual are the ones only a human can judge, like confirming the UI still renders correctly. When you're working with Skia or other GPU-drawn views, plan to glance at the screen each pass: the wizard drives the metrics, you confirm it still looks right. Kick it off with "buoy optimize".
Buoy tools run inside your app and sync to a local broker over the external-sync protocol. The MCP server connects to that broker as a "Dashboard" client — the same role the Buoy desktop app plays — or spawns its own broker in-process when no desktop app is running, so it works standalone.