Guide · The architectural decision the QA-flavored MCP guides skip
Browser MCP for recruiter automation: read everything, draft writes, fire nothing without approval.
Most browser MCP guides on the open web are written by QA tooling vendors. Their target is a fresh test fixture and their failure mode is a flaky assertion. Recruiter automation is a different shape. The target is a real candidate, the failure mode is a mis-fired stage move that lands in the candidate’s timeline, and the regulator (NYC DCWP, Illinois IDOL, the Colorado AG, an EU AI Act notified body) wants to see the recruiter who approved the action and the surface the agent saw. This guide walks the shape that survives that audit.
Direct answer · verified 2026-05-06
How do you use a browser MCP for recruiter automation
Use a browser MCP server (Microsoft’s playwright-mcp with 70+ tools, or the Chrome DevTools MCP) only for reads and proposed actions. Never let the agent autonomously click Move stage or Send message on a real candidate. Wrap every write tool to emit a draft anchored to a role-and-accessible-name target, route the draft through a human approval queue, and on approval, fire the actual write through the public ATS API where it exists, falling back to a role+name browser_click only for surfaces the API does not cover. Capture the tree before and after; that is the audit row a 2026 hiring-law regulator will accept.
01The mismatch
QA targets are reversible. Recruiter targets are not.
The dominant browser MCP guides on the open web read like a unit-testing playbook. Spin a fresh browser, snapshot the tree, click the button, assert the next state. If something breaks, throw the run away and start again. That is the right shape for the use case those guides were written about, which is a developer running Playwright MCP against a CI fixture or a staging environment.
A recruiter ATS is the opposite shape. Every browser_click on Move to onsite writes a row in the candidate timeline. Every browser_click on Send draft emails the candidate. The most recent ATSes log every state change with an actor, and a candidate who later asks why was I rejected is going to receive that log. There is no fixture to restore. The action is the product, and the action is irreversible the moment it crosses the candidate-facing surface.
That is the gap the existing browser MCP literature does not cover. Microsoft publishes a 70+ tool surface that includes both reads and writes. The README is neutral about which to expose. The Ashby Claude MCP community guidance is the opposite, and it is the more honest one: start in read-only, restrict the write tools, build your own approval surface. That advice generalizes. Browser MCP is the same shape, one layer down. The protocol does not care; the architecture you wrap around it has to.
The autonomous shape vs. the draft-and-approve shape
Same browser MCP, same accessibility tree, same Ashby candidate page. The first snippet is what most demos do. The second snippet is what 10xats does and what the audit row needs.
// what most "browser MCP for recruiting" demos look like // agent runs autonomously; every tool call is a live candidate touch await mcp.call("browser_navigate", { url: "https://app.ashbyhq.com/candidate/" + candidateId, }); await mcp.call("browser_snapshot"); // ~ 8 KB of ARIA, 2k tokens await mcp.call("browser_click", { ref: "button[name='Move stage']", // fires the modal }); await mcp.call("browser_click", { ref: "option[name='Onsite']", // candidate just moved }); await mcp.call("browser_click", { ref: "button[name='Confirm']", // candidate-visible event }); // no approval surface // no audit row keyed to a role+name target // no rollback if Sonnet hallucinated the candidateId // no defense under LL144 / HB 3773 / CAIA / EU AI Act high-risk hiring
- browser_click reaches the candidate with no human in between
- The action target is a CSS-selector ref, not a role+name pair
- No before/after tree hash; the audit row is unverifiable
- Every turn streams back the full snapshot (~114K tokens benchmark)
02The five-step shape
Snapshot, resolve, draft, approve, fire
The smallest architecture that wraps a browser MCP into something a recruiter can ship without taking on personal liability under the 2026 hiring laws.
Snapshot the tree, not the pixels
Call browser_snapshot or browser_evaluate to read the candidate page through its accessibility tree. The tree is the surface a screen reader sees, dense and semantically labeled, and stable across UI redesigns because changing it would break a published WCAG conformance claim. CSS selectors and pixel coordinates do not survive the next refactor.
Resolve the action to a role + accessible-name target
Find the control by role (button, listbox, dialog, textbox) and accessible name (Move stage, Onsite, Confirm). Capture both. The role and the name are the audit-row anchors; class hashes and XPath are not. If the role+name pair cannot be found, write a fallback row noting that the integration dropped to a less stable selector.
Emit a draft, not a live click
Wrap every browser write tool so that instead of firing browser_click, it returns a draft object: target, prior tree slice, intended action, and the claim-ledger rationale. The draft lands in Gmail, Slack, or the in-product approval queue. Nothing has reached the candidate yet.
Approve, then fire the actual write
When the recruiter taps approve, the draft fires. Prefer the public ATS API (Greenhouse Harvest, Lever Data API, Workday Recruiting REST, Ashby Public API) for surfaces it covers. Fall through to a role+name browser_click for surfaces it does not. Capture the after-tree snapshot. Hash both. Write one audit row.
Replay any decision against the audit row
Every row carries actor, tool, target (role+name plus rendered text), prior_state, new_state, and the content hash of both tree slices. NYC DCWP, Illinois IDOL, the Colorado AG, and EU AI Act notified bodies can replay any decision because the row contains both the surface the agent saw and the surface it produced. CSS-selector logs and pixel logs cannot.
The wire-level draft
What an approved write looks like at the call site. The agent calls browser_snapshot, the draft helper computes the role+name target and queues the action, and the API path is preferred over the browser click for the actual fire.
03What the queue produces
One approve tap. One audit row. Two tree hashes.
A real fire-after-approve session. The CLI is illustrative; the same loop runs inside the web queue and inside the Gmail draft. The audit row is the artifact a regulator will replay.
The shape, end to end
Reads stream straight through the MCP. Writes branch into the approval queue and only fire on tap. The audit log is keyed to the same role+name target the recruiter saw.
Browser MCP wired through an approval queue
04Per-vendor surface
Same shape across the four ATSes that buy this work today
Role+name targets for the move-to-stage action plus the public-API path that the draft prefers when the recruiter approves. Names captured against current production UIs as of 2026-05-06; they drift, the integration health check re-snapshots weekly.
| Vendor | Role | Accessible name | Preferred API path | Note |
|---|---|---|---|---|
| Greenhouse | button | "Move" | Harvest API: POST /v1/applications/:id/move | Stage transitions live in the candidate header. |
| Lever | button | "Advance" | Data API: POST /v1/opportunities/:id/stage | Advance fires the configured next stage; pin the source stage. |
| Workday Recruiting | button | "Change Stage" | Recruiting REST: candidates/{id}/applications/{id}/stages | Opens a modal listbox; the API skips the modal entirely. |
| Ashby | button | "Move stage" | Public API: POST /candidate.changeStage | Lowercase 's' in stage; the casing matters for accessible-name match. |
The decision matrix
Two architectures, same browser MCP underneath. The right column is what fails on audit; the left column is what survives.
| Feature | Autonomous browser MCP loop | Draft-and-approve (10xats shape) |
|---|---|---|
| Read tools | browser_navigate, browser_snapshot, browser_evaluate | browser_navigate, browser_snapshot, browser_evaluate |
| Write tools | Direct browser_click against the candidate UI | Wrapped to emit a draft for the approval queue |
| Action target | CSS selector, ref, or pixel coordinates | Role + accessible name pinned to a tree slice |
| Approval surface | None; the agent loop fires the action | Gmail, Slack, or the in-product queue, one-tap |
| Audit row | Tool-call log without before/after surface evidence | Actor, tool, target, before-tree hash, after-tree hash |
| Compliance shape | Recruiter or staffing agency on the hook for the gap | Reproduces what LL144, IL HB 3773, CO CAIA, EU AI Act expect |
| Token cost per turn | Full snapshot streamed back on every turn (~114K tokens) | Same MCP cost; reads only, writes route through API |
“The approval queue is the product. Every sourcing and scheduling action shows up as a draft I click through in 30 seconds between calls.”
Recruiter on a 18-req week, 10xats waitlist briefing
05Token economics
Why MCP is not always the right transport for the read path
The Microsoft playwright-mcp server returns the full accessibility snapshot in the tool response on every browser_navigate and browser_snapshot. Pramod Dutta’s February 2026 benchmark on Medium clocked a typical browser-automation turn at roughly 114,000 tokens through MCP versus 27,000 tokens through the equivalent Playwright CLI variant, which writes the snapshot to a YAML file on disk and returns a one-line path the agent can choose to read.
For a recruiter loop walking 200 candidate pages a day, the difference is roughly a 4x bill on Sonnet pricing. The community recommendation is consistent across the Bug0, TestDino, and TestCollab analyses: pick MCP when the agent runs sandboxed (Claude Desktop, ChatGPT, custom chat UIs) where MCP is the only transport available; pick the CLI when the agent is shell-capable (Claude Code, Cursor, Copilot) and can read the YAML file off disk on demand.
For the 10xats shape, the read path can be either, and the write path is always the draft-and-approve queue. The audit-row anchor (role + accessible name + tree hash) is the same in both cases. The transport is an optimization; the architecture is the safety guarantee.
06Compliance shape
What the audit row has to contain in 2026
NYC DCWP’s Local Law 144, Illinois HB 3773 (effective January 2026), Colorado CAIA (effective February 2026), and the EU AI Act high-risk hiring rules do not require the same artifacts in the same format, but they overlap on three things: a human approved the candidate-facing decision, the rationale is on file, and the surface the agent operated on is recoverable.
A browser MCP loop that fires browser_click autonomously satisfies none of those. A draft-and-approve loop satisfies all three: the recruiter who tapped approve is the actor, the claim ledger from Match Rating is the rationale, and the role+name target plus the before/after tree hashes is the surface evidence. The audit row replays the decision exactly.
See the companion guides on the accessibility-tree integration shape, Anthropic Claude as the front door, and ATS security and compliance for AI agents for the rest of the picture, plus claim-by-claim resume scoring for the rationale field on every audit row.
Wire your browser MCP into an approval queue, not into a candidate
Join the 10xats waitlist. The Sourcing, Scheduling, and Match Rating agents ship with the queue and the audit-row shape on day one, on the Starter $0 plan.
Frequently asked questions
What is a browser MCP, exactly?
A Model Context Protocol server that exposes a live browser session to an AI agent through a fixed set of tools. The two reference implementations in 2026 are Microsoft's playwright-mcp (70+ tools, accessibility-tree-first, no vision model required) and the Chrome DevTools MCP from the ChromeDevTools org (40+ tools, deep DevTools integration via Puppeteer). Anthropic introduced the protocol in November 2024; by early 2026 the SDK had crossed 97 million downloads and shipped on Claude Desktop, ChatGPT, Cursor, Copilot, and most coding agents. The agent calls browser_navigate, browser_snapshot, browser_click, browser_type, and the underlying browser does the work.
Why is using a browser MCP against a recruiter ATS different from using one for QA testing?
Every action on a QA target is reversible inside the test harness: spin a fresh browser, restore a fixture, throw the run away. Every action on a recruiter ATS is irreversible the moment it crosses a candidate-facing surface. browser_click on Move to onsite advances a stage and writes a row in the candidate timeline. browser_click on Send draft fires an email. There is no fixture to restore. The 2026 hiring laws (NYC DCWP Local Law 144, Illinois HB 3773, Colorado CAIA, the EU AI Act high-risk hiring rules) all assume a human approved the candidate-facing action and the rationale is auditable. A browser MCP that fires browser_click autonomously gives you neither.
Does the Ashby Claude MCP have this problem too?
Yes, and the community guidance acknowledges it. The Ashby Claude MCP exposes 33 distinct tools mapped to the Ashby API, including writes for stage moves, notes, and outreach. Almost every public Ashby and Greenhouse Claude MCP setup recommends starting in read-only mode and explicitly filtering out the write tools, precisely because the ATS itself has no human-in-the-loop spine and a generic MCP write reaches the candidate without any approval surface in between. Browser MCP is the same shape, one layer down: instead of wrapping the API, it wraps the UI, but the lack of an approval queue is identical.
What does the Playwright MCP token cost actually look like for a recruiter loop?
Microsoft's playwright-mcp returns the full accessibility snapshot in the tool response on every browser_navigate or browser_snapshot. A typical browser-automation turn measured by Pramod Dutta in February 2026 burned around 114,000 tokens through MCP versus roughly 27,000 through the equivalent Playwright CLI, which writes the snapshot to a YAML file on disk and returns a one-line path. For a recruiter loop walking 200 candidates a day, that is the difference between a $20 and an $80 LLM bill on Sonnet pricing. Most public benchmarks recommend MCP for sandboxed agents (Claude Desktop, ChatGPT) and CLI for shell-capable agents (Claude Code, Cursor, Copilot).
If I am going to use a browser MCP anyway, what is the minimum-viable safe shape?
Three rules. First, separate reads from writes: every read tool is exposed (browser_navigate, browser_snapshot, browser_evaluate); every write tool is rewrapped to emit a draft, not a live action. Second, anchor every draft to a role-and-name target read off the accessibility tree, never to CSS classes or pixel coordinates, so the audit row is something a regulator can verify against the surface a screen reader sees. Third, write the draft into an approval queue (Gmail, Slack, web view, your call) and fire the actual click only after a recruiter taps approve. The queue is the product; the browser MCP is the transport.
When should I prefer the public ATS API over a browser MCP click?
Always, when the API covers the surface. Greenhouse Harvest, Lever Data API, Workday Recruiting REST, and the Ashby Public API all cover candidate read, candidate write, application stage transitions, and event webhooks. The browser MCP is for the long tail: a custom scorecard field a customer added in the admin panel, a vendor-specific dropdown, a multi-step approval modal, anything behind a feature flag the API has not caught up to. Use the API for the 80% the API ships and fall through to a role+name browser_click for the 20% it does not. Both produce the same audit row shape.
Will browser MCP work on Greenhouse, Lever, Workday Recruiting, and Ashby specifically?
Yes for reads, and yes for writes once you put an approval queue in front of the writes. All four publish WCAG 2.1 or 2.2 AA conformance because federal procurement requires a VPAT, which makes the accessibility tree dense and stable enough to script against deterministically. The accessible name varies per vendor (Move on Greenhouse, Advance on Lever, Change Stage on Workday, Move stage on Ashby) so the selector is per-vendor, but the integration shape is identical: snapshot, find by role and name, queue the action, fire on approval.
What about Chrome DevTools MCP versus Playwright MCP for this use case?
Either works for reads. Chrome DevTools MCP from the ChromeDevTools org leans into performance tracing, network inspection, and Puppeteer-based automation, with about 40+ tools and slim-mode support. Playwright MCP from Microsoft is the more general browser-automation surface with 70+ tools and explicit accessibility-tree-first execution. For recruiter loops the deciding factor is rarely the MCP itself; it is whether the agent runs sandboxed (Claude Desktop, ChatGPT, where MCP is the only option) or shell-capable (Claude Code, Cursor, Copilot, where the CLI variant cuts tokens roughly 4x).
Does this give me a defensible audit log under NYC LL144, Illinois HB 3773, Colorado CAIA, and the EU AI Act?
It can, if you wire it correctly. The audit row written for each action carries: actor (the agent identifier and the recruiter who approved), tool (ats.move_stage, ats.send_message, ats.draft_email), target (a role and accessible-name pair plus the rendered text snapshot of the affected node), prior_state (the tree slice before), new_state (the tree slice after), and a content hash of both. Regulators auditing under any of those four regimes can replay any decision because the audit row contains both the surface the agent saw and the surface it produced. CSS-selector logs and pixel logs are not the same artifact and have repeatedly failed the disparate-impact-and-notice review at the staffing-agency level.
Where does 10xats sit in this picture?
10xats ships pattern two from day one on the Starter $0 plan: a Sourcing, Scheduling, and Match Rating agent graph with browser-driven writes wrapped as drafts in a one-tap approval queue, anchored to role+name accessibility-tree targets, and exposed through both an MCP server and ChatGPT integration. The product is in development; the pricing, the architectural commitments, and the public roadmap are on the home and pricing pages, the rest of this guide is the playbook to apply if you are wiring a browser MCP into your existing ATS today and do not want to wait.