feat: add built-in browser mcp server with attach mode and orange indicator frame - #197
Merged
Conversation
**Added:** - EPIPE fallthrough in claude live session loop so the initial stdin write no longer masks the more diagnostic exited-without-a-result error carrying the CLI's stderr tail - `agenticcli/claude_live.go` - Regression test pinning the initial-write EPIPE race that surfaced as a flaky broken-pipe error on slow CI runners - `agenticcli/claude_live_test.go` - `--remote-debug` flag on `squad browser open` to opt into Chrome's remote-debugging endpoint, kept off by default since it grants any local process control of the browser and its logged-in sessions - `cmd/squad/browser.go`, `browser/launch.go` - `--profile` flag on `squad mcp server browser` to attach the MCP server to an already-running squad browser session instead of launching a new headless browser, sharing the user's login state - `cmd/squad/mcp_server.go` - `--no-sandbox` flag on `squad mcp server browser` (previously hardcoded) so sandbox-weakening is explicit - `cmd/squad/mcp_server.go` - `attachToActivePage` helper that connects to a profile's active session, targets its first real page (skipping chrome://, devtools://), and detaches without closing the user's tab - `cmd/squad/browser_eval.go` - Per-tool timeout (`browserToolTimeout`, 2m) bound to the request context so a hung page load cannot wedge the MCP server forever - `cmd/squad/mcp_server.go` - Tests covering the attach-mode path, profile/user-data-dir conflict, missing-session error, and verification that server teardown leaves the user's tab open - `cmd/squad/mcp_server_test.go`, `cmd/squad/browser_eval_test.go` - `requireChrome` test helper and shared `chromeExecOpts` that pin test browser discovery to the same lookup `browser.Launch` uses and skip cleanly on machines without Chrome - `cmd/squad/mcp_server_test.go` **Changed:** - Renamed `findChrome` to exported `FindChrome` so the MCP server can reuse squad's Chrome discovery (SQUAD_BROWSER_BIN, then Google Chrome before Chromium) instead of chromedp's own preference order - `browser/launch.go`, `browser/launch_test.go`, `cmd/squad/mcp_server.go` - `squad browser eval` now returns results as JSON (via `json.RawMessage`) and maps `ErrJSUndefined`/`ErrJSNull` to literal `undefined`/`null` instead of Go's default formatting - `cmd/squad/browser_eval.go` - `evaluate_js` MCP tool now returns JSON output with the same undefined/null handling for consistency with the CLI - `cmd/squad/mcp_server.go` - Better error message from `browser.ActivePort` pointing users at `squad browser open NAME --remote-debug` when no session is found - `browser/active.go` - MCP browser server refactored around a `browserServerOptions` struct and split into `connectBrowserServer` / `runBrowserAction` helpers; profile mode is mutually exclusive with `--user-data-dir` - `cmd/squad/mcp_server.go` - Live eval test now navigates to a probe page and asserts `document.body.innerText` to prove eval runs in the session's open page rather than a fresh blank tab - `cmd/squad/browser_eval_test.go` - Live browser test timeouts bumped from 10s to 30s to accommodate slower Chrome startup - `cmd/squad/browser_eval_test.go`, `cmd/squad/mcp_server_test.go` - Promoted `github.com/chromedp/cdproto` from indirect to direct dependency for `target.Info` use in page-target selection - `go.mod` **Removed:** - `runBrowserServer` wrapper — callers use `runBrowserServerIO` directly with the new options struct - `cmd/squad/mcp_server.go` - Unconditional `--remote-debugging-port=0` from `browser.Launch`; now gated behind `RemoteDebug` so profile setup no longer exposes a CDP endpoint by default - `browser/launch.go`
**Changed:** - Documented the built-in browser MCP server as an alternative to `chrome-devtools-mcp@latest` in the browser command help, showing the `squad mcp server browser` invocation with `--profile` - Clarified the `mcp server browser` long help to note it speaks standard MCP over stdio (usable regardless of model provider), tightened the `--profile` description, and added an `agent.yaml` wiring example for `mcp_servers`
**Added:** - Visible in-page indicator when the browser MCP server attaches to a running Chrome session — orange frame plus a "squad" badge — so users can always see which tab an agent is driving (`cmd/squad/browser_indicator.go`) - `installAttachIndicator` injects the indicator into the current document and pins it across future navigations via `Page.addScriptToEvaluateOnNewDocument`, returning a best-effort remove func with a 5s timeout for detach - Test coverage in `TestMCPServerAttachMode` verifying the indicator is present after attach, survives navigation, and is removed on cleanup without disturbing the user's page **Changed:** - `connectBrowserServer` in `cmd/squad/mcp_server.go` now installs the indicator after attaching and composes its removal into the cleanup chain; install failure aborts the attach since visibility is the whole point of driving a real browser - `--profile` help text documents the new visual indicator behavior
**Added:** - `scrubProfileDir` test helper in `cmd/squad/mcp_server_test.go` that registers a tolerant `t.Cleanup` retrying `os.RemoveAll` for up to 10 seconds, working around Chrome helper processes still flushing profile files after the allocator reports the browser gone - `scrubProfileDir` call in `TestMCPServerAttachMode` and `TestBrowserEvalLiveSuccess` so their Chrome profile dirs under `t.TempDir` are drained before the strict TempDir cleanup runs, preventing "directory not empty" flakes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Key Changes:
squad mcp server browser) that can either launch its own headless browser or attach to an already-running Chrome session via--profile, sharing the user's login state without requiring npx or external MCP packagesPage.addScriptToEvaluateOnNewDocumentsquad browser evalto attach to the session's first real page (skippingchrome:///devtools://targets), preserve the tab on detach by nulling the chromedp target before cancel, and emit results as JSONAdded:
--profile,--user-data-dir,--headless, and--no-sandboxflags, plus a 2-minute per-tool timeout that aborts on request cancellation -cmd/squad/mcp_server.gocmd/squad/browser_indicator.goattachToActivePagehelper that resolves the DevTools endpoint, picks the first real page target, and returns a cleanup that detaches without closing the tab -cmd/squad/browser_eval.go--remote-debugflag onsquad browser open(off by default) since the CDP endpoint gives any local process full control of the browser and its cookies -cmd/squad/browser.go,browser/launch.gocmd/squad/mcp_server_test.go,cmd/squad/browser_eval_test.go,agenticcli/claude_live_test.gochromeExecOpts,scrubProfileDir(tolerant retry cleanup for Chrome's post-exit file flushing), andrequireChrome(cached skip-if-unavailable probe) -cmd/squad/mcp_server_test.goChanged:
browser.FindChromeso the MCP server and tests pin Chrome discovery to the same order (SQUAD_BROWSER_BIN, Google Chrome, then Chromium) instead of chromedp's default preference -browser/launch.goevaluate_jsandbrowser evalnow return raw JSON (with explicitundefined/nullhandling viachromedp.ErrJSUndefined/ErrJSNull) instead of Go's%vformattingActivePorterror message now suggests the exactsquad browser open NAME --remote-debuginvocation to fix the missing endpoint -browser/active.gorunBrowserServerIOrefactored around abrowserServerOptionsstruct and a newconnectBrowserServerthat dispatches between attach and launch paths, with cleanup composed so allocator cancel runs after browser cancel -cmd/squad/mcp_server.goHELLO-EVAL-PROBE) to prove the command runs in the session's open page rather than a blank tab -cmd/squad/browser_eval_test.go,cmd/squad/mcp_server_test.gogithub.com/chromedp/cdprotopromoted from indirect to direct dependency for thepage.AddScriptToEvaluateOnNewDocument/target.Infousage -go.mod