Arthur
Lightweight Headless Chromium Runtime & MCP Server for AI Agents
Direct CDP WebSockets • Semantic Ref-ID Snapshots • Persistent Python REPL • FastMCP Server
Overview
Arthur is a standalone, lightweight headless Chromium runtime engineered specifically for AI agents (such as Gloria, Claude, and autonomous coding assistants).
Arthur eliminates browser extensions, native messaging hosts, and heavy automation drivers by connecting directly to Chromium via Chrome DevTools Protocol (CDP) WebSockets. It manages an ephemeral sandboxed Chromium process, retains persistent Python REPL state across turns, and generates concise, token-efficient semantic DOM snapshots with assigned Ref-IDs ([#1], [#2]).
Agent / MCP Client
│
▼ execute_python(code)
FastMCP Server (stdio / Streamable HTTP)
│
▼
Python REPL Session (stateful memory & auto-snapshots)
│
▼
Arthur Browser API (synchronous facade)
│
▼ CDP WebSockets
Headless Chromium (--headless=new)
Quickstart
1. Instant Zero-Clone Execution via uvx
No repository cloning or manual environment management is required:
# Run MCP Server (stdio transport)
uvx --from git+https://github.com/sh7vansh/arthur arthur mcp
# Run Interactive Terminal REPL
uvx --from git+https://github.com/sh7vansh/arthur arthur repl
# Run One-Shot Command
uvx --from git+https://github.com/sh7vansh/arthur arthur repl -c "browser.navigate('https://example.com'); print(browser.snapshot())"
2. Connect to MCP Clients (Claude Desktop, Cursor, etc.)
Add Arthur to your MCP settings configuration (e.g. claude_desktop_config.json):
Using uvx (Zero-Clone):
{
"mcpServers": {
"arthur": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/sh7vansh/arthur",
"arthur",
"mcp"
]
}
}
}
Using Local Repository:
{
"mcpServers": {
"arthur": {
"command": "uv",
"args": [
"--directory",
"/path/to/Arthur",
"run",
"arthur",
"mcp"
]
}
}
}
Local Installation
Prerequisites
- Python 3.10+
- uv package manager
- Google Chrome or Chromium (Arthur automatically discovers existing local installations)
# Clone the repository
git clone https://github.com/sh7vansh/arthur.git
cd arthur
# Install dependencies in an isolated virtual environment
uv sync --all-extras
Key Capabilities
1. In-Page Semantic DOM Engine & Ref-IDs
Arthur evaluates an in-page accessibility parser that extracts the visible DOM, calculates WAI-ARIA accessible roles/names, and generates a compact, token-efficient semantic tree with assigned numeric Ref-IDs:
PAGE: "Example Domain" (https://example.com)
- heading[level=1] "Example Domain"
- paragraph: "This domain is for use in illustrative examples in documents."
- link [#1] "More information..." (href="https://www.iana.org/domains/example")
Agents target elements directly using Ref-IDs (1, "[#1]"), avoiding brittle CSS or XPath selectors.
2. Coordinate-Accurate Synthetic Input
Translates high-level agent actions into coordinate-precise CDP events:
browser.click(target): Resolves bounding center coordinates and dispatchesInput.dispatchMouseEvent.browser.type(target, text, press_enter=True): Focuses the element, clears existing input, inserts text, and simulates real key events.browser.select(target, value): Handles<select>dropdown menus.browser.hover(target)&browser.scroll(x, y): Simulates mouse hover and viewport/element scrolling.
3. Persistent Stateful Python REPL
The execute_python tool retains variables, functions, and imports across successive agent turns:
# Turn 1: Define helper and fetch data
import json
browser.navigate("https://news.ycombinator.com")
titles = browser.eval_js("[...document.querySelectorAll('.titleline > a')].map(a => a.innerText)")
# Turn 2: State persists across tool calls
print(f"Captured {len(titles)} articles:")
print(titles[:3])
4. Single-Turn Self-Healing & Diagnostics
- Diagnostic Auto-Snapshot: When an unhandled exception occurs, Arthur automatically captures the latest DOM snapshot (
[diagnostic_auto_snapshot]) and appends it to the error payload, allowing the agent to self-heal in a single turn without extra roundtrips. - Fuzzy Suggestions: If an element reference becomes stale after a dynamic DOM mutation, Arthur provides fuzzy match suggestions from snapshot history.
5. Output Budgeting & Telemetry Defanging
All execution output passes through a strict budgeting pipeline:
- Prevents context window explosion by truncating output exceeding token/character limits.
- Automatically defangs tracking image beacons (
->[IMAGE_BLOCKED]) and unsafe active HTML tags.
Python API Reference
The synchronous browser instance is pre-injected into the REPL environment:
# --- Navigation & Inspection ---
browser.navigate("https://example.com", timeout=30.0)
snapshot_text = browser.snapshot()
current_url = browser.url
page_title = browser.title
# --- Synthetic Interactions (Ref-ID, String Ref, or CSS Selector) ---
browser.click(1) # Click Ref-ID #1
browser.click("[#1]") # String Ref-ID format
browser.click("button.submit-btn") # CSS selector fallback
browser.type(2, "search query", press_enter=True)
browser.select(3, "Option Value")
browser.hover(1)
browser.scroll(x=0, y=500)
# --- Synchronization & Waiting ---
browser.wait_for(1, state="visible", timeout=10.0)
browser.wait_for_url(r"^https://example\.com/dashboard", timeout=15.0)
# --- Evaluation & Captures ---
result = browser.eval_js("window.innerWidth")
png_bytes = browser.screenshot()
text_content = browser.get_text(1)
attr_value = browser.get_attribute(1, "data-custom")
# --- Multi-Tab Management ---
new_tab = browser.new_tab("https://google.com")
tabs = browser.tabs # List of open Tab instances
active = browser.active_tab
tab_2 = browser.get_tab(2)
browser.close_tab(2)
Remote Deployment & Transports
Arthur supports multiple network transports for remote, cloud, and containerized deployments.
1. Stateless Streamable HTTP (Recommended for Remote / Cloud)
For remote servers, VMs, Docker containers, Cloudflare Tunnels, and reverse proxies, Stateless Streamable HTTP is the most reliable transport.
Why Stateless HTTP is Superior for Remote Setups:
- Resilient to Network Drops: Unlike stateful SSE connections that drop or report "Session Expired" when a network glitch occurs between agent turns, stateless HTTP treats each tool execution as an independent request.
- Proxy & Tunnel Friendly: Works cleanly behind Nginx, Cloudflare Tunnels, AWS ALBs, and Ngrok without hitting idle connection timeouts (e.g. 60s stream timeouts).
- Preserved Backend State: While the HTTP wire transport is stateless, Arthur's in-memory Python REPL session, Chromium browser instance, cookies, and open tabs remain fully persistent on the server.
Starting Stateless Streamable HTTP:
# Start server on remote host (listening on 0.0.0.0:8000)
uv run arthur mcp --transport streamable-http --stateless --host 0.0.0.0 --port 8000
Client Configuration:
{
"mcpServers": {
"arthur": {
"url": "http://remote-server-ip:8000/mcp"
}
}
}
2. SSH Stdio Tunneling (Zero-Port Remote Access)
Run Arthur securely over SSH without opening public firewall ports:
{
"mcpServers": {
"remote-arthur": {
"command": "ssh",
"args": [
"user@remote-host",
"uvx --from git+https://github.com/sh7vansh/arthur arthur mcp"
]
}
}
}
3. Server-Sent Events (/sse)
For legacy MCP clients requiring standard SSE endpoints:
uv run arthur mcp --transport sse --host 0.0.0.0 --port 8000
- Endpoint:
http://<host>:8000/sse
Testing & Development
Run the test suite to validate CDP WebSocket transport, headless Chromium lifecycle, in-page DOM operations, and persistent REPL execution:
# Run pytest test suite
uv run pytest
# Run type checker
uv run mypy src
License
This project is licensed under the MIT License — see the LICENSE file for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arthur_runtime-0.1.0.tar.gz.
File metadata
- Download URL: arthur_runtime-0.1.0.tar.gz
- Upload date:
- Size: 155.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ac63fd16101c1f6271e339d6f0460354def6eb5422e02f1995094f44a882fd6
|
|
| MD5 |
f4e0903e464ae407d0cc645548e30b94
|
|
| BLAKE2b-256 |
bd4a4d51fe22f53c5ca57aee92b24dd4c7946522c04f66164327716e710f070f
|
File details
Details for the file arthur_runtime-0.1.0-py3-none-any.whl.
File metadata
- Download URL: arthur_runtime-0.1.0-py3-none-any.whl
- Upload date:
- Size: 34.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
353e2991dc165a5863425c0270d9d8892b5d8ffcd2579a33a72abd362111339d
|
|
| MD5 |
6742b5c3ed091dcfe672bcc900b48e86
|
|
| BLAKE2b-256 |
12e8c13be649d6b7fc56080a2dd339afc212a4ce701fd703dc794f8ef449f721
|