Skip to main content

servo-agent

An agent-controllable browser, built on the Servo engine.

ci license python live demo

Status: pre-1.0 / alpha — the API may change. Feedback and contributions welcome.

servo-agent — a robot giving life to a web page

Live product page → servo-agent.brownfamilysports.com — the /pc kiosk ("Easy as 1-2-3" animation) + the /info page (use cases, quickstart).

servo-agent turns a Servo build into a browser an LLM agent can drive — and, crucially, read. It wraps Servo's built-in W3C WebDriver server (a control surface LLMs already understand) and adds the one thing agents actually need: read_page, which distills the post-render DOM into clean markdown, with scripts, navigation chrome and citation markup removed and links kept absolute.

It runs headless, manages the engine lifecycle for you, and ships as an MCP server so you can drop it straight into Claude Code, Codex, or any MCP client.

            ┌──────────────┐   W3C WebDriver    ┌────────────────┐
  agent ──▶ │  servo-agent │ ─────────────────▶ │   servoshell   │ ──▶ the web
  (MCP)     │  (this repo) │ ◀───────────────── │  (Servo engine)│
            └──────────────┘   DOM → markdown    └────────────────┘

Why

Most "agent browsing" stacks puppeteer Chromium over CDP: heavyweight, hard to instrument, and easy to bot-detect. Servo is a memory-safe, embeddable engine you can own end to end. Because it already speaks WebDriver, an agent is immediately on familiar ground — and because you control the engine, you can extend it at the source (see the roadmap).

The payoff is read_page: an agent reads distilled content, not tag soup.

Measured on 2026-10-21 (reproducible — uv run python bench/read_page_bench.py):

Page Rendered HTML Distilled markdown Reduction read_page returns
playwright.dev docs (Docusaurus SPA) 134 KB 5 KB 27× 5 KB
Wikipedia, "Web browser" 597 KB 36 KB 16× 12 KB (capped)
RFC 2616 on rfc-editor.org 2 MB 452 KB 4× 12 KB (capped)
Hacker News front page 34 KB 17 KB (links kept) 2× 12 KB (capped)

Pages built around navigation and boilerplate shrink the most; a page that is mostly text (the RFC) or mostly links (Hacker News) shrinks the least. Separately, read_page returns at most 12,000 characters unless you raise max_chars, so one call never floods an agent's context.

Install

servo-agent is not on PyPI yet. Install it from this repository:

uv tool install git+https://github.com/parker-brown-family/servo-agent

pipx install git+https://github.com/parker-brown-family/servo-agent works too. To work from a clone instead, run uv sync in it and put uv run in front of the commands below.

You also need a built servoshell, Servo's browser binary. Put it on PATH, set $SERVOSHELL, or check out Servo next to this repository and build it:

./mach build -d --media-stack dummy  # -> target/debug/servoshell

servo-agent looks for it in this order: $SERVOSHELL, then PATH, then a built servo/ checkout beside this repository, or beside any directory above the installed package (so a project that installs servo-agent, such as servo-reader, finds a servo/ checkout beside itself).

Every tool works with stock Servo except read_native, which needs the /servo/agent/read endpoint from the t3/native-read branch of our Servo fork. On other builds read_native answers {"available": false} and read_page does the reading.

Quick start

# Prove the whole stack end-to-end (spawns its own headless engine):
servo-agent selftest https://news.ycombinator.com

# Run as an MCP server (stdio):
servo-agent serve

Library use:

from servo_agent import ServoBrowser, distill

with ServoBrowser(headless=True) as b:
    b.navigate("https://example.com")
    print(distill(b.read_html(), b.current_url()))   # clean markdown
    rows = b.extract_table("table#stats")            # structured data
    b.screenshot("shot.png")

Tools (MCP)

Tool Purpose
open_url Navigate; returns title/url once the new document has committed (settle to wait out SPA hydration).
read_page Post-render DOM → clean markdown (the value-add).
read_native In-engine read: {url, title, text, headings, links} with no JS round-trip (needs the fork's endpoint, see Install).
find / wait_for_selector Query / wait for elements by CSS selector.
wait_for_load Wait for readyState=complete and a quiescent DOM (post-load hydration).
get_errors Best-effort JS error capture (uncaught / rejection / failed resource).
click / type_text / fill_form Interaction.
scroll Scroll to bottom/top, a selector, or a pixel offset.
extract_links / extract_table Structured extraction → JSON.
eval_js Run JavaScript, get JSON back.
screenshot / status Capture (optional width/height/full_page) / introspect.

Wire into an MCP client

Claude Code

claude mcp add servo-agent -s user -- servo-agent serve

From a clone, run it through uv instead:

claude mcp add servo-agent -s user -- \
  uv run --project /path/to/servo-agent servo-agent serve

Codex (~/.codex/config.toml)

[mcp_servers.servo-agent]
command = "uv"
args = ["run", "--project", "/path/to/servo-agent", "servo-agent", "serve"]

MCP tools are injected at client startup — restart after adding/changing the server. Validate harness edits without a restart via servo-agent selftest.

Observability

Every tool call is recorded to a structured JSONL log — the product feedback loop, built for agents to consume (not a human dashboard). It captures what only the server can see: distill extractor + compression ratio, fallbacks, errors, engine respawns, latency.

servo-agent events                 # rolled-up digest (rates, latency, distill ratios)
servo-agent events --tail 50       # raw recent events (JSONL)
servo-agent events --tool read_page --errors

Log at $SERVO_AGENT_LOG (default ~/.servo-agent/events.jsonl); set SERVO_AGENT_LOG=off to disable. Details in docs/observability.md.

Known limits

  • Pages Servo never finishes loading. Many real pages stay at readyState: interactive in Servo because a web font or analytics beacon never completes (servo.org itself does). open_url returns once such a page's DOM has been still for two seconds and reports interactive; the content is readable.
  • Screenshots of those pages time out after Servo's 10-second limit (#3).
  • One session, no saved profile: no cookies across runs, no tabs, no downloads. Login-gated flows still need a fuller browser.
  • click → back() → reload() in the Python API hits a Servo WebDriver bug and answers 500 (#5). Each call works on its own.

Use cases

Worked, runnable examples live in examples/ and the integration adapters in integrations/:

  • Research source-reader — distilled markdown for multi-source research.
  • Site QA / pre-deploy checker — render, screenshot, assert content & links.
  • Page watcher — poll a page, extract a value, alert on change.
  • Bot-walled scrape fallback — a JS-rendering engine you own.
  • Structured data extraction — extract_table into a pipeline.
  • Universal "read the live web" primitive for any agent task.

See docs/use-cases.md for the full write-up.

Develop

uv sync --extra dev
uv run pytest            # unit tests always run; integration auto-skips w/o a binary
uv run ruff check .

Contributing

Contributions are welcome — see CONTRIBUTING.md for dev setup and the workflow. On your first pull request you sign the CLA once, by posting the comment the CLA bot asks for. Please be kind (Code of Conduct) and report vulnerabilities privately (SECURITY.md). Changes are logged in CHANGELOG.md.

License

Apache-2.0 — see LICENSE and NOTICE. Servo itself is a separate project under MPL-2.0; servo-agent talks to it over WebDriver and does not vendor its code.

Metadata

Release files for servo-agent 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for servo-agent 0.2.0
File Size Uploaded Provenance Actions
servo_agent-0.2.0.tar.gz 199.8 kB With provenance Details for servo_agent-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for servo-agent 0.2.0
File Interpreter ABI Platform Actions
servo_agent-0.2.0-py3-none-any.whl Python 3 none any Details for servo_agent-0.2.0-py3-none-any.whl

Total release size: 237.3 kB

Release files / servo_agent-0.2.0.tar.gz

Download URL servo_agent-0.2.0.tar.gz
Size 199.8 kB
Tags Source
SHA-256 checksum
How to use checksums
11ef7bc1ffee637c5d13148ed367b6c7c0c25aeb57279ba56450b0333a6fa758
BLAKE2b-256 checksum
How to use checksums
4be2bf230241aaf1e281e0543550b898e30a7a2e62d6923211b66f55232b9f45
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Release files / servo_agent-0.2.0-py3-none-any.whl

Download URL servo_agent-0.2.0-py3-none-any.whl
Size 37.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e248607a69c18ad9a2846037d4b7b4aa5fd40f891bb5bee6f828e285eab18d44
BLAKE2b-256 checksum
How to use checksums
711aeb36e3eb1e089a4313ad492c7958fc23a5b8ae1b2d3cb7cdf1ea12b8276a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Security for servo-agent 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for servo_agent-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page