Skip to content

feat: add built-in browser mcp server with attach mode and orange indicator frame - #197

Merged
l50 merged 4 commits into
mainfrom
worktree-gemini-commit-fixes
Aug 17, 2026
Merged

feat: add built-in browser mcp server with attach mode and orange indicator frame#197
l50 merged 4 commits into
mainfrom
worktree-gemini-commit-fixes

Conversation

@l50

@l50 l50 commented Aug 17, 2026

Copy link
Copy Markdown
Member

Key Changes:

  • Added a built-in browser MCP server (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 packages
  • Introduced a visible agent-control indicator (orange border + "squad" badge) that frames any page an agent is driving through the attach mode, persisting across navigations via Page.addScriptToEvaluateOnNewDocument
  • Hardened squad browser eval to attach to the session's first real page (skipping chrome:// / devtools:// targets), preserve the tab on detach by nulling the chromedp target before cancel, and emit results as JSON
  • Fixed a flaky EPIPE race in the claude-live agentic CLI where an early CLI death on the initial prompt write masked the more diagnostic exited-without-a-result error

Added:

  • Browser MCP server with --profile, --user-data-dir, --headless, and --no-sandbox flags, plus a 2-minute per-tool timeout that aborts on request cancellation - cmd/squad/mcp_server.go
  • Attach-mode indicator injection and removal helpers with idempotent CSS + badge and best-effort teardown - cmd/squad/browser_indicator.go
  • attachToActivePage helper 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-debug flag on squad 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.go
  • Test coverage for attach mode (indicator presence across navigations, teardown leaves the page alive), profile/user-data-dir conflict, missing session, and initial-write EPIPE fallthrough - cmd/squad/mcp_server_test.go, cmd/squad/browser_eval_test.go, agenticcli/claude_live_test.go
  • Shared test helpers chromeExecOpts, scrubProfileDir (tolerant retry cleanup for Chrome's post-exit file flushing), and requireChrome (cached skip-if-unavailable probe) - cmd/squad/mcp_server_test.go

Changed:

  • Exported browser.FindChrome so 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.go
  • evaluate_js and browser eval now return raw JSON (with explicit undefined/null handling via chromedp.ErrJSUndefined/ErrJSNull) instead of Go's %v formatting
  • ActivePort error message now suggests the exact squad browser open NAME --remote-debug invocation to fix the missing endpoint - browser/active.go
  • runBrowserServerIO refactored around a browserServerOptions struct and a new connectBrowserServer that dispatches between attach and launch paths, with cleanup composed so allocator cancel runs after browser cancel - cmd/squad/mcp_server.go
  • Live browser test timeouts raised from 10s to 30s and the eval test now asserts against a real page body (HELLO-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.go
  • github.com/chromedp/cdproto promoted from indirect to direct dependency for the page.AddScriptToEvaluateOnNewDocument / target.Info usage - go.mod

l50 added 3 commits August 17, 2026 10:48
**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
@github-actions github-actions Bot added the area/go Changes made to Go source code (cmd/, config/, logging/) label Aug 17, 2026
**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
@l50 l50 changed the title fix: prevent EPIPE masking exit diagnosis and harden browser tooling feat: add built-in browser mcp server with attach mode and orange indicator frame Aug 17, 2026
@l50
l50 merged commit 54816d6 into main Aug 17, 2026
5 checks passed
@l50
l50 deleted the worktree-gemini-commit-fixes branch August 17, 2026 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/go Changes made to Go source code (cmd/, config/, logging/)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant