The Web, Readable.
Charlotte is an MCP server that renders web pages into structured, agent-readable representations using headless Chromium. Agents control how much context they receive — from a 364-character orientation to the full page — so they never pay for what they don't need.
Benchmarks
Charlotte v0.8.0 vs Playwright MCP v0.0.79 on real websites, measured 2026-08-08. Every character an MCP server returns enters the agent's context window — smaller responses mean lower costs, more room for reasoning, and longer browsing sessions.
Characters returned when an agent first lands on a page. Charlotte defaults to minimal detail; Playwright returns the full accessibility tree.
The workflow difference: Playwright agents receive 50K+ characters every time they look at Hacker News — whether they're reading headlines or looking for a login button. Charlotte agents get 364 characters on arrival, call find({ type: "link", text: "login" }) to get exactly what they need, and never pay for the rest.
What Charlotte Returns
Agents control how much context they receive. Navigate returns a compact orientation; observe returns the full element list when needed.
{
"url": "https://news.ycombinator.com",
"title": "Hacker News",
"viewport": { "width": 1280, "height": 720 },
"structure": {
"headings": [
{ "level": 1, "text": "Hacker News", "id": "h-a1b2" }
]
},
"interactive_summary": {
"total": 93,
"by_landmark": {
"(page root)": { "link": 91, "text_input": 1, "button": 1 }
}
}
}Detail Levels
minimalsummaryfullStable Element IDs
Hash-based IDs survive DOM mutations and element reordering.
btn-a3f1buttoninp-c7e2text inputlnk-d4b9linksel-e8a3selectchk-f1a2checkboxfrm-b1d4form43 Tools, 8 Categories
Everything an agent needs to navigate, understand, and interact with the web.
Navigation
4Browse the web. Go to URLs, traverse history, refresh pages.
navigatebackforwardreloadObservation
7Understand pages. Three detail levels, spatial search, visual capture, structural diffing.
observefindscreenshotscreenshotsscreenshot_getscreenshot_deletediffInteraction
13Act on pages. Click, type, submit forms, drag elements, scroll, and poll for async conditions.
clickclick_attypeselecttogglesubmitscrollhoverdragkeywait_foruploadfill_formSession
11Manage browser state. Tabs, viewports, network throttling, cookies, headers.
tabstab_opentab_switchtab_closeviewportnetworkget_cookiesclear_cookiesset_cookiesset_headersconfigureDev Mode
3Local development. Static server with hot reload, CSS/JS injection, accessibility audits.
dev_servedev_injectdev_auditUtility
2Execute arbitrary JavaScript in page context. Handle browser dialogs (alert, confirm, prompt).
evaluatedialogMonitoring
2Inspect runtime behavior. Retrieve console messages and network request history with filters.
consolerequestsMeta
1Manage tool visibility at runtime. List, enable, and disable tool groups without restarting.
toolsUsage Examples
Once connected as an MCP server, agents can use Charlotte's tools directly.
Browse a website
// Navigate to a page
navigate({ url: "https://example.com" })
// See what's on the page
observe({ detail: "summary" })
// Find a specific element
find({ type: "link", text: "About" })
// Click it
click({ element_id: "lnk-a3f1" })Quick Start
Get Charlotte running in under a minute. No install required — npx handles everything for local MCP clients. Want to connect from claude.ai instead? Self-host Charlotte Remote with a single Docker command.
1Use It From Claude Code / Any Stdio MCP Client
Claude Code — create .mcp.json in your project root:
{
"mcpServers": {
"charlotte": {
"type": "stdio",
"command": "npx",
"args": ["@ticktockbent/charlotte"],
"env": {}
}
}
}Claude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"charlotte": {
"command": "npx",
"args": ["@ticktockbent/charlotte"]
}
}
}2Self-Host Charlotte Remote for claude.ai
One command stands up Charlotte as a network-reachable MCP server you connect from claude.ai instead of a local client:
docker run --cap-add SYS_ADMIN --shm-size 2g -p 3737:3737 ghcr.io/ticktockbent/charlotteStands up a public tunnel URL and an operator token, and prints the connector strings for claude.ai — paste the URL into Settings → Connectors → Add custom connector, leave OAuth Client ID/Secret blank, and enter the token when prompted.
3Verify It Works
navigate({ url: "https://example.com" })
// Returns: 612 chars — title, landmarks, headings, interactive counts
find({ type: "link" })
// Returns: matching elements with IDs ready for interactionOptional: For faster startup (skips npx resolution), install globally:
npm install -g @ticktockbent/charlotteThen replace "command": "npx" with "command": "charlotte" in your config.
Charlotte reviews this site.
This site uses Charlotte to check itself. An agent serves it locally with dev_serve, inspects the rendered page with observe, and runs dev_audit for accessibility, SEO, and contrast — switching to a mobile viewport and reading element bounding boxes to catch what a skim would miss.
That loop has caught real bugs: 16 unlabeled SVG icons invisible to sighted reviewers but broken for screen readers, and a 204-pixel horizontal overflow on mobile. Both were fixed in the session they were introduced.
That's what it means to make the web readable.