Skip to content

feat: AUTO-247 stamp x-browserless-client marker on agent WS upgrades#177

Closed
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1784059444-mcp-client-source
Closed

feat: AUTO-247 stamp x-browserless-client marker on agent WS upgrades#177
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1784059444-mcp-client-source

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Stamp an x-browserless-client header on every /chromium/agent WebSocket upgrade so enterprise Amplitude can distinguish agent traffic that comes through the MCP server from direct WS clients.
  • Default the marker to mcp, but forward a recognized inbound sub-source (currently script_generator) end-to-end so the Script Generator's traffic is attributable separately.
  • Keep the marker in HTTP headers only — never in the query string — so it doesn't land in URL logs (the token already lives in the URL).

Related issues

Changes

  • src/lib/agent-client.ts: add buildClientHeaders(clientSource?) and pass it as the headers option on the single new WebSocket(...) call, so the normal, sessionId-attach, profile-create and reconnect flows all carry the marker. Also advertises x-browserless-client-name / x-browserless-client-version from package.json (best-effort; failures just omit them). getOrCreateSession accepts a clientSource, stores it on the ActiveSession, and replays it on reconnect.
  • src/lib/http-auth.ts: read inbound x-browserless-client, normalizing it — only script_generator is forwarded verbatim; anything else (including missing/untrusted values) collapses to mcp, so a raw client can't impersonate an arbitrary source at the MCP boundary.
  • src/index.ts, src/lib/define-tool.ts, src/tools/agent.ts, src/@types/types.d.ts: thread the resolved source through request → auth → session → ToolRunContext → agent tool → getOrCreateSessionconnect.
  • Tests: header-capturing upgrade server + assertions that the default mcp marker lands on a normal connect, that script_generator is forwarded verbatim, and that the sessionId attach flow also carries the marker (with sessionId still in the URL).

Enterprise reads this header on the agent endpoint and maps it to a source (mcp | script_generator | direct) dimension on its Amplitude Browser Session Ended events (separate PR in browserless/enterprise, plus a small browserless/server event-type change).

Test plan

  • npm test passes locally (459 passing, incl. 3 new marker tests)
  • npm run lint passes locally
  • npm run coverage thresholds still met
  • Manual smoke test against a real Browserless token (describe below)
  • N/A — docs / chore / refactor only

Checklist

  • I have read CONTRIBUTING.md
  • My commits follow the conventional-commit prefix convention
  • I have updated documentation where relevant (README, CHANGELOG, etc.)
  • I have not introduced new dependencies without flagging them in the summary

Link to Devin session: https://app.devin.ai/sessions/e83e8132735c4677b42f3a470a8090fe
Requested by: @xsvfat

Summary by CodeRabbit

  • New Features
    • Added client attribution to agent WebSocket connections through the x-browserless-client header.
    • Preserved client attribution across browser sessions, reconnects, and session attachments.
    • Added support for forwarding the script_generator client marker while defaulting other connections to mcp.
  • Tests
    • Added coverage confirming client markers are sent in headers and excluded from WebSocket URLs.

Co-Authored-By: Sean Yang <sean@browserless.io>
@xsvfat xsvfat self-assigned this Jul 14, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author
Original prompt from Sean Yang

Goal: Distinguish agent traffic originating from the MCP server versus direct WebSocket clients in Amplitude, by stamping an x-browserless-client: mcp header at the MCP boundary and propagating a source property into the agent's Amplitude events.

#``# Repo 1: browserless/browserless-mcp
File: src/lib/agent-client.ts

  • The agent WebSocket URL is built by buildAgentWsUrl (around lines 254-283) and the connection is opened with new WebSocket(...) in this same file, which already passes a headers option object.
  • Add an identifying header x-browserless-client: mcp to the headers option on the new WebSocket(...) upgrade call. Optionally also include the MCP package version and client name (e.g. x-browserless-client-version) for finer breakdowns, sourced from package.json.
  • Ensure the marker is applied on ALL agent WS connections, including the early-return sessionId attach path — since the header is set on the WebSocket connect (not the URL), verify both the normal and sessionId flows go through the same new WebSocket call that now carries the header.
  • Do NOT put the marker in the query string (the token is already there; keep the marker out of URL logs).

#``# Repo 2: browserless/enterprise
Endpoint classification stays path-based (/chromium/agentEndpointType.AGENT) in src/utils.ts; do not change that. Add a separate source dimension.

File: src/shared/browserql/agent/agent-api.ts

  • The class AgentAPI already reads request headers in its constructor (see how it reads req.headers['x-browserless-max-file-size-mb'] around lines 119-126 to compute maxFileTransferBytes). In the same place, read x-browserless-client from req.headers and store an instance field, e.g. this.source = headers?.['x-browserless-client'] === 'mcp' ? 'mcp' : 'direct'.
  • There are ~11 .send( call sites in this file and 2 in src/shared/browserql/agent/utils.ts and 1 in src/shared/browserql/agent/agent.chromium.ws.ts. The Amplitude event sends are... (1936 chars truncated...)

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds client-source attribution to authentication, agent session context, WebSocket upgrade headers, reconnects, and tests. The default mcp marker and script_generator sub-source are propagated without placing the marker in the WebSocket URL.

Changes

Client source attribution

Layer / File(s) Summary
Source resolution and tool propagation
src/@types/types.d.ts, src/lib/http-auth.ts, src/index.ts, src/lib/define-tool.ts, src/tools/agent.ts
Authentication maps incoming headers to clientSource, exposes it in session and tool context, and passes it through both agent session setup paths.
WebSocket header and session lifecycle
src/lib/agent-client.ts, src/@types/types.d.ts
The agent client derives package metadata, sends attribution headers, stores clientSource on sessions, and reuses it during reconnects.
Upgrade header validation
test/helpers/upgrade-server.ts, test/lib/agent-client.spec.ts
Tests capture WebSocket upgrade requests and verify default, custom, attach-flow, and URL-isolation behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AgentTool as browserless_agent
  participant Session as getOrCreateSession
  participant Connect as connect
  participant WS as WebSocket
  AgentTool->>Session: Pass clientSource
  Session->>Connect: Create session with clientSource
  Connect->>WS: Send x-browserless-client headers
  Session->>Session: Store clientSource on ActiveSession
  Session->>Connect: Reuse clientSource on reconnect
Loading

Possibly related PRs

Suggested reviewers: andymrtnzp, artiom

Poem

A rabbit hops with headers bright,
mcp guides the WebSocket flight.
A source is stored through every run,
Reconnects keep what was begun.
No marker hides within the URL—
Thump, thump, the tests all tell!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and clearly states the main change: adding the x-browserless-client marker to agent WebSocket upgrades.
Description check ✅ Passed The description matches the required template and covers summary, issues, changes, test plan, and checklist with useful detail.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch devin/1784059444-mcp-client-source

Comment @coderabbitai help to get the list of available commands.

@devin-ai-integration devin-ai-integration Bot changed the title feat: stamp x-browserless-client marker on agent WS upgrades feat: AUTO-247 stamp x-browserless-client marker on agent WS upgrades Jul 14, 2026
@andyMrtnzP andyMrtnzP closed this Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants