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 336-character orientation to the full page — so they never pay for what they don't need.

$npx @ticktockbent/charlotte
136xsmaller than Playwright
7tools to start, 42 when you need them
3detail levels
MITlicense

Benchmarks

Charlotte v0.2.0 vs Playwright MCP on real websites. 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.

Wikipedia (AI)136x smaller
Charlotte
7,667
Playwright
1,040,636
Hacker News182x smaller
Charlotte
336
Playwright
61,230
GitHub repo25x smaller
Charlotte
3,185
Playwright
80,297
example.com1.3x smaller
Charlotte
612
Playwright
817

The workflow difference: Playwright agents receive 61K+ characters every time they look at Hacker News — whether they're reading headlines or looking for a login button. Charlotte agents get 336 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.

PageRepresentation
{
  "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

minimal
~50-200Landmarks, headings, interactive counts by region
summary
~500-5000Full element list, forms, content summaries
full
variableEverything in summary, plus all visible text

Stable Element IDs

Hash-based IDs survive DOM mutations and element reordering.

btn-a3f1button
inp-c7e2text input
lnk-d4b9link
sel-e8a3select
chk-f1a2checkbox
frm-b1d4form

40 Tools, 8 Categories

Everything an agent needs to navigate, understand, and interact with the web.

Navigation

4

Browse the web. Go to URLs, traverse history, refresh pages.

navigatebackforwardreload

Observation

4

Understand pages. Three detail levels, spatial search, visual capture, structural diffing.

observefindscreenshotdiff

Interaction

10

Act on pages. Click, type, submit forms, drag elements, scroll, and poll for async conditions.

clicktypeselecttogglesubmitscrollhoverdragkeywait_for

Session

9

Manage browser state. Tabs, viewports, network throttling, cookies, headers.

tabstab_opentab_switchtab_closeviewportnetworkset_cookiesset_headersconfigure

Dev Mode

3

Local development. Static server with hot reload, CSS/JS injection, accessibility audits.

dev_servedev_injectdev_audit

Utility

2

Execute arbitrary JavaScript in page context. Handle browser dialogs (alert, confirm, prompt).

evaluatedialog

Monitoring

2

Inspect runtime behavior. Retrieve console messages and network request history with filters.

consolerequests

Meta

1

Manage tool visibility at runtime. List, enable, and disable tool groups without restarting.

tools

Usage Examples

Once connected as an MCP server, agents can use Charlotte's tools directly.

Browse a website

tool calls
// 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. Just add the config and go.

1Add to Your MCP Client

Claude Code — create .mcp.json in your project root:

.mcp.json
{
  "mcpServers": {
    "charlotte": {
      "type": "stdio",
      "command": "npx",
      "args": ["@ticktockbent/charlotte"],
      "env": {}
    }
  }
}

Claude Desktop — add to claude_desktop_config.json:

claude_desktop_config.json
{
  "mcpServers": {
    "charlotte": {
      "command": "npx",
      "args": ["@ticktockbent/charlotte"]
    }
  }
}

2Verify It Works

verification
navigate({ url: "https://example.com" })
// Returns: 612 chars — title, landmarks, headings, interactive counts

find({ type: "link" })
// Returns: matching elements with IDs ready for interaction

Optional: For faster startup (skips npx resolution), install globally:

npm install -g @ticktockbent/charlotte

Then replace "command": "npx" with "command": "charlotte" in your config.

This page was built by an agent.

An AI agent designed this entire website, wrote every component, and shipped it in a single session — with no human reviewing screenshots or testing on a phone.

It didn't need to. Charlotte gave it eyes.

The agent served the site locally with dev_serve, inspected the rendered page with observe, and ran dev_audit to check accessibility, SEO, and contrast. It switched to a mobile viewport, detected that code blocks were overflowing past the edge of the screen by reading element bounding boxes, fixed the CSS, and verified the fix — all without a human ever looking at the page.

Charlotte caught 16 unlabeled SVG icons that would have been invisible to sighted reviewers but broken for screen readers. It found a 204-pixel horizontal overflow on mobile that would have shipped unnoticed. Both bugs were fixed in the same session they were introduced.

That's what it means to make the web readable.