Buoy MCP

Inspect and drive a running React Native or Flutter app, simulator farms and Chrome from your editor

Official · Buoy TypeScript Local · stdio Developer toolsTesting

62 popularity score ★ 695 ↓ 1.5k/wk

Connect your client

Local (npm)

Add in one click

Opens the app, which asks before it adds the server.

Or add it by command or config

Claude CodeTerminal
claude mcp add buoy -- npx -y @buoy-gg/mcp@latest
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "buoy": {
      "command": "npx",
      "args": [
        "-y",
        "@buoy-gg/mcp@latest"
      ]
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "buoy": {
      "command": "npx",
      "args": [
        "-y",
        "@buoy-gg/mcp@latest"
      ]
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "buoy": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@buoy-gg/mcp@latest"
      ]
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.buoy]
command = "npx"
args = ["-y", "@buoy-gg/mcp@latest"]
Gemini CLITerminal
gemini mcp add --scope user buoy npx -- -y @buoy-gg/mcp@latest

Settings 7

Set together: sign-in
BUOY_KEY secret Optional: Backup account value when the computer is not signed in with buoy login. BUOY_LICENSE_KEY is checked first, then this name and its EXPO_PUBLIC_, VITE_, NEXT_PUBLIC_ or REACT_APP_ forms in the project's env files.
BUOY_PROJECT_ROOT Optional: App project folder used for the env file lookup and .buoy files.
BUOY_SECRET_NAME secret Optional: One per secret, with NAME replaced. Typed in place of {{secret:NAME}} and masked in what the tool returns. For native_type.
BUOY_CHROME_PATH Optional: Chrome binary to use instead of the chrome-headless-shell the farm downloads. For Chrome Farm.
BUOY_FARM_HOME Optional: Folder where the Sim Farm keeps its simulators and state. Default ~/.buoy/farm. For Sim Farm.
BUOY_TELEMETRY Optional: Set to 0, false or off to stop Buoy Web's daily usage ping. DO_NOT_TRACK=1 does the same. For Buoy Web.
Set together: broker
BUOY_BROKER_PORT Optional: Port of the local broker. Default 42831.

What it does

Buoy is a set of in-app developer tools for React Native and Flutter apps, and @buoy-gg/mcp is the MCP server that ships with it. The in-app tools sync to a local broker. This server joins that broker as a dashboard client, the same role Buoy Desktop plays, or starts a broker of its own when Desktop isn't running. From there your editor's assistant can see which devices are connected and read the screen as a list of elements. It can tap, swipe and type, run multi-step flows, take screenshots or recordings, and read console output and captured requests.

Pro opens up the inside of the app: Zustand, Redux, Jotai and React Query state, storage values, request bodies and mocked responses, plus overrides for network speed, the clock, location and permissions. A free account keeps the basic set and Buoy Optimize, which covers the benchmark tools and the Sim Farm but leaves component names out of its results.

The bundle registers 112 tools, many more than the docs name. Two newer groups work outside your app. The Sim Farm (sim_farm_*) clones slim iOS simulators or Android emulators from a template build and leases them out, so an agent can try many fixes side by side. The Chrome Farm (chrome_farm_*) starts headless Chrome instances on a web app, each with its own storage and a memory cap. You can drive both from a shell too, with `npx -y @buoy-gg/mcp@latest farm`.

The same package also holds a second server called Buoy Web, set up with `init --web`. It works websites in Chrome with real clicks and key presses, and nothing has to be installed in an app. Its guide now names all 15 of its tools: open, read, click, type, key, wait, scroll, drag, hover, select, tabs, dialog and logs, plus upload and screenshot. With the Buoy Web extension it works in your own Chrome profile. Without the extension it opens a separate Chrome window that keeps its sign-ins in ~/.buoy/web-profile. It is free and needs no account.

What it needs

RuntimeNode.js 18+
Runs onmacOS, Windows, Linux
BuoyFree tierFree covers the basic tools, Optimize and Buoy Web. Pro adds app state, storage, request bodies and overrides.
Also
  • A running app with Buoy devtools and @buoy-gg/external-sync, for the app tools only
  • Xcode on macOS, or adb, for screenshots, real touches and device control
  • A Mac with Xcode or the Android tools, for the Sim Farm
  • Google Chrome, for Buoy Web and the Chrome Farm

Sign the computer in once by running `npx --package=@buoy-gg/core buoy login` in the app folder. The server uses that sign-in and needs nothing else, though it falls back to an account value in the project's env files. The app tools need `@buoy-gg/external-sync` in the app, running as a development build (React Native) or a debug build (Flutter). Buoy Web needs nothing in the app. Its Chrome extension is optional.

Limits

  • Cost Most tools need Buoy Pro. On a free account a Pro tool replies that it needs Pro and nothing reaches the app, except on Saturdays and Sundays under the Weekend Pass.
  • Early release Platforms other than React Native are in beta.
  • Platform describe_screen, tap_element, reload_app, network conditions and JS-thread profiling work on React Native only.
  • Platform The Sim Farm runs on Macs only. Its Android emulators are tested on Apple Silicon Macs.
  • Not covered Slim farm simulators have no push, StoreKit purchases, app links, widgets or Spotlight. A stock template is the way around that.
  • Size cap Screen recordings stop at 3 minutes.
  • Limit A server older than the Desktop broker is refused, so the two have to be updated together.
  • Rate limit Each Buoy Web call stops after 60 seconds by default (BUOY_WEB_CALL_LIMIT_MS).
  • Not covered Buoy Web uploads only files inside the working folder or BUOY_WEB_UPLOAD_DIRS, and it refuses .env files and anything under .ssh or .aws.
  • Limit run_web_benchmark still tells you to add Playwright to the project, although the package already depends on playwright-core.

Most tools need Buoy Pro; on a free account a Pro tool answers that it needs Pro and nothing reaches the app. Buoy is proprietary software under Buoy's terms. Several features are React Native only (UI driving with describe_screen/tap_element, reload_app, network conditions, JS-thread profiling, buoy-optimize). native_pinch does not work on Android; native_inspect shows only the app's side on a physical iPhone. Recordings stop at 3 minutes. Network conditions reset on a JS reload, do not affect native transports outside fetch/XHR, and are a development preview. An MCP version older than the Desktop broker is refused, so both must be updated together.

Who it suits

Suits React Native or Flutter developers who use Buoy already, or can add it to their app, and want an editor assistant to reproduce bugs, look at state and network traffic, and check a fix on a device or simulator. The deeper tools sit behind the paid Pro plan. Performance work on a Mac gets the most out of the farms. Someone who only wants an assistant working in Chrome can use Buoy Web alone, free and without an account. It is a poor fit for apps that can't take Buoy's in-app packages, or for teams that need open-source tooling, since Buoy is proprietary.

Tools 60 of 112

28 only read, 29 change things, 3 can delete or overwrite. A ? marks an optional parameter.

list_devices
Lists the apps connected to Buoy and the tools each one offersdetails?: booleanincludeDisconnected?: boolean
list_tool_actions
Shows the actions a Buoy tool accepts and which devices offer ittoolId?: stringtool?: stringdeviceId?: string
get_snapshot
Reads the current synced state of one Buoy tool on a devicetoolId?: stringtool?: stringdeviceId?: stringtimeoutMs?: number
call_action changes
Runs any action a Buoy tool exposes and returns its resulttoolId?: stringtool?: stringaction: stringparams?: anyargs?: anydeviceId?: stringtimeoutMs?: number
get_events
Returns retained network, state, route and storage events, with filterslimit?: numbersources?: arraystatus?: enumincludeData?: booleanformat?: enumpreset?: enumdeviceId?: string
get_triage
Sums up recent console errors, requests and storage key names for an appdeviceId?: string
describe_screen
Lists on-screen React elements with text, roles, testIDs and positionsinteractiveOnly?: booleanincludeBuoy?: booleanincludeHidden?: booleandeviceId?: string
tap_element changes
Calls an element's press, value or text handler in JavaScriptnativeTag?: numbertestID?: stringquery?: stringvalue?: anytext?: stringlongPress?: booleanscrollIntoView?: booleanincludeBuoy?: booleanincludeHidden?: booleanobserve?: enumdeviceId?: string
native_tap changes
Sends a real OS touch on the simulator or phonelabel?: stringquery?: stringtestID?: stringnativeTag?: numberx?: numbery?: numberholdMs?: numberallowBuoy?: booleanserial?: stringdeviceId?: string
native_type changes
Types text on the device keyboard into the focused fieldtext: stringserial?: stringdeviceId?: string
native_swipe changes
Sends a real swipe or drag, and can scroll until the end of a listdirection?: enumfromX?: numberfromY?: numbertoX?: numbertoY?: numberdurationMs?: numberdrag?: booleanuntilEnd?: booleanallowBuoy?: booleanserial?: stringdeviceId?: string
native_pinch changes
Pinches, spreads or turns with two fingers on iOSx?: numbery?: numberscale?: numberrotate?: numberdurationMs?: numberallowBuoy?: booleandeviceId?: string
native_inspect
Reads native controls on the screen, or the one at a pointpointX?: numberpointY?: numberx?: numbery?: numberserial?: stringdeviceId?: string
run_flow changes
Runs a sequence of UI steps and checks, stopping at the first failure
screenshot_component
Takes a screenshot, optionally compared against a saved baselinecompareTo?: stringquery?: stringnativeTag?: numberscrollIntoView?: booleanserial?: stringbaseline?: stringupdateBaseline?: booleansteady?: booleanthreshold?: numberignore?: arrayignoreAreas?: arraydeviceId?: string
screen_recording
Starts and stops a screen recording on the simulator or Android deviceaction: enumname?: stringsteps?: arrayserial?: stringdeviceId?: string
device_control changes
Rotates, shakes or otherwise works the device itselfaction: enumorientation?: enumtext?: stringmatch?: booleanfingerId?: integerserial?: stringdeviceId?: string
lifecycle_action deletes
Sends the app to the background or interrupts it, and can quit, relaunch or reinstall it with its data wipedaction: enumduration?: anyskipWait?: booleanurl?: stringscheme?: enummode?: enumlevel?: numberlowPowerMode?: booleanstate?: enumid?: stringshowChip?: booleanreportWindow?: anyreal?: booleanappPath?: stringkeepBuoySignIn?: booleansimulator?: stringudid?: stringserial?: stringdeviceId?: string
reload_app changes
Asks a supported app to reload its JavaScriptstrategy?: enumwait?: booleantimeoutMs?: numberdeviceId?: string
get_routes
Lists the app's routes, with a sitemap on requestincludeSitemap?: booleandeviceId?: string
navigate changes
Moves the app to a route pathpath: stringreplace?: booleanobserve?: enumdeviceId?: string
get_console
Reads the tail of captured console output, filtered by level or patternlevel?: enumlimit?: numberpattern?: stringdeviceId?: string
get_network_requests
Lists captured HTTP requests with status, timing and sizelimit?: numberpattern?: stringstatus?: enumflagged?: enumincludeBodies?: booleandeviceId?: string
get_network_request
Reads one captured request in full by its idid: stringmaxChars?: numberdeviceId?: string
network_action changes
Pins or saves captured requests, or clears the listsaction: enumid?: stringkey?: stringdeviceId?: string
network_conditions changes
Reads or sets simulated network speed and offline stateaction: enumprofile?: enumconnection?: enumdeviceId?: string
network_override changes
Sets mock responses, failures or delays for matching requestsaction: enumurlPattern?: stringfromRequestId?: stringmethods?: arraykind?: enumstatus?: numberbody?: anybodyPatch?: objectstatusText?: stringheaders?: objectfailKind?: enumdelayMs?: numbertimes?: numberalternate?: booleanname?: stringenabled?: booleanid?: stringurl?: stringmethod?: stringdeviceId?: string
get_storage
Reads storage keys across AsyncStorage, MMKV and Expo SecureStorepattern?: stringincludeValues?: booleanlimit?: numberdeviceId?: string
get_redux_state
Reads the app's Redux stateincludeValues?: booleandeviceId?: string
redux_dispatch changes
Dispatches a Redux action to the app's storetype: stringpayload?: anydeviceId?: string
time_machine_action changes
Captures, previews and restores snapshots of app stateaction: enumid?: stringname?: stringmode?: enumexcludeKeys?: arrayrestoreRoute?: booleansourceIds?: arraydeviceId?: string
clock_action changes
Moves, freezes or speeds up the clock the app readsaction: enumtime?: anyby?: anyfreeze?: booleanfireTimers?: booleanrate?: numberpersist?: booleanshowChip?: booleanfireTimersOnJump?: booleantoken?: stringleadMs?: numberstatus?: numbertimes?: numberdeviceId?: string
location_action changes
Pins the location the app sees, or plays a routeaction: enumlatitude?: numberlongitude?: numberlabel?: stringquery?: stringplace?: stringpoints?: arrayroute?: stringto?: stringspeed?: numberheading?: numberloop?: booleanmeters?: numberfraction?: numberidentifier?: stringtask?: stringconditions?: enumon?: booleanaccuracy?: numberjitter?: number
permission_action changes
Overrides the answer the app gets when it asks for a permissionaction: enumpermission?: stringstate?: enumanswer?: enumnotifyApp?: booleaninterceptSettings?: booleanenforce?: booleanpersist?: booleanshowChip?: booleandeviceId?: string
run_benchmark_batch
Runs a benchmark batch across cases and ranks them per metrictargetRoute: stringcases: arraybounceRoute?: stringrunsPerCase?: numberperCaseDurationMs?: numbersettleMs?: numbercoolDownMs?: numbernavTimeoutMs?: numberdiscardWarmupRuns?: numbershuffleCases?: booleanreloadBetweenCases?: booleancaptureRenders?: booleandeviceId?: stringmaxWaitMs?: number
measure_renders
Counts component renders during given steps or an idle windowsteps?: arrayidleMs?: numberlabel?: stringcompareToPrevious?: booleantop?: numberdeviceId?: string
get_js_thread_top
Samples JavaScript task origins with busy percentage and freezesdeviceId?: stringdurationMs?: numberclearFirst?: boolean
get_component_source
Finds where a React view is used in the project codequery?: stringnativeTag?: integerdeviceId?: string
native_profile
Traces native CPU work on the iOS Simulator or Android
memory_check
Starts or stops a memory leak check in a native dev builddeviceId?: stringaction: enumbaselinePath?: stringtargetPath?: stringcycles?: integersettleMs?: integerrunId?: string
camera_source changes
Gives the iOS Simulator a camera and picks what it showskind: enumvalue?: stringformat?: enum
sim_farm_status
Shows the Sim Farm's simulators and who is using themoutside?: boolean
sim_farm_setup changes
Creates or resizes the Sim Farm from an app buildmode: enumplatform?: enumapkPath?: stringphone?: stringreverse?: arraytemplateId?: stringcount?: integerappPath?: stringseedDir?: stringlaunchUrl?: stringdeviceType?: stringruntime?: stringprofile?: enummetroPort?: integerdryRun?: boolean
sim_farm_acquire changes
Leases farm simulators for a run, optionally launching the app on eachcount: integergoal?: stringlabels?: arraykind?: enumrunId?: stringpurpose?: stringtemplateId?: stringplatform?: enumlaunch?: booleanallowPartial?: booleanwaitSeconds?: integerttlMinutes?: integer
sim_farm_action changes
Screenshots, launches, resets or rebuilds leased simulators, or installs an .apk on Android copiesleaseId: stringepoch: integerudids: arrayaction: enumurl?: stringapkPath?: string
sim_farm_release deletes
Gives a lease's simulators back and resets their app dataleaseId: stringepoch: integerreset?: enumkeepRun?: boolean
sim_farm_finish changes
Ends a farm run with a result and frees its simulatorsoutcome?: enumsummary?: string
chrome_farm_status
Shows running Chrome Farm instances with memory, CPU and debug ports
chrome_farm_up changes
Starts Chrome instances on a web app, each with its own storage and memory capurl: stringcount?: integerready?: stringviewport?: enumcapMB?: integerlabel?: stringboost?: booleangpu?: boolean
chrome_farm_down changes
Closes Chrome Farm instances
chrome_farm_screenshot
Takes a screenshot of one Chrome Farm instanceid: string
run_web_benchmark
Benchmarks variants of a web page in a fresh headless Chromiumurl: stringpath?: stringcases?: arrayrunsPerCase?: numberperCaseDurationMs?: numbersettleMs?: numbercpuSlowdown?: arrayviewport?: objectreadySelector?: stringsteps?: arraytraceDir?: stringheaded?: booleanallowPageErrors?: booleanprojectRoot?: stringoutFile?: stringextraRoundsWhenClose?: numbermaxBatchMs?: numberbudgets?: object
find_web_ceiling
Finds the most load each web variant holds at a target frame rateurl: stringpath?: stringcases?: arrayparam: stringstart?: numbergrowth?: numbermax?: numbertargetFps?: numberprecisionPct?: numberrounds?: numbermaxBatchMs?: numbersettleMs?: numbermeasureMs?: numbercpuSlowdown?: numberviewport?: objectreadySelector?: stringheaded?: booleanprojectRoot?: string
get_native_profile
Reads a native trace by its id, with hot functions and a short report
get_memory_leaks
Reads a memory check's suspects and progressdeviceId?: stringrunId?: stringkind?: enumlimit?: integer
sim_farm_lock changes
Holds or frees a machine-wide lock tied to a lease, such as a slot for fair speed testsleaseId: stringepoch: integername: stringhold: booleanwaitSeconds?: integer
sim_farm_report changes
Posts run progress that the person watches in Buoy Desktopudid?: stringstate?: enumnote?: stringcounts?: objectresultSource?: enumsequence?: integer
sim_farm_extend changes
Asks for more minutes on a farm run, up to the run's capminutes: integer
chrome_farm_reset deletes
Clears an instance's cookies, storage and caches and reloads its app
chrome_farm_pause changes
Pauses or wakes Chrome Farm instances, keeping their page and storage

Similar servers