The Web, Readable.

Charlotte is an MCP server that renders web pages into structured, agent-readable representations using headless Chromium. Navigation, observation, and interaction — without vision models or brittle selectors.

$npm install charlotte-web
30MCP tools
6categories
222tests passing
MITlicense

What Charlotte Returns

Every page is decomposed into a structured representation optimized for token efficiency. Agents receive landmarks, headings, interactive elements, bounding boxes, and form structures.

PageRepresentation
{
  "url": "https://example.com/dashboard",
  "title": "Dashboard",
  "viewport": { "width": 1280, "height": 720 },
  "snapshot_id": 1,
  "structure": {
    "landmarks": [
      { "role": "banner", "label": "Site header",
        "bounds": { "x": 0, "y": 0, "w": 1280, "h": 64 } },
      { "role": "main", "label": "Content",
        "bounds": { "x": 240, "y": 64, "w": 1040, "h": 656 } }
    ],
    "headings": [
      { "level": 1, "text": "Dashboard", "id": "h-1" }
    ],
    "content_summary": "main: 2 headings, 5 links, 1 form"
  },
  "interactive": [
    {
      "id": "btn-a3f1",
      "type": "button",
      "label": "Create Project",
      "bounds": { "x": 960, "y": 80, "w": 160, "h": 40 },
      "state": { "enabled": true, "visible": true }
    }
  ],
  "forms": [],
  "alerts": [],
  "errors": { "console": [], "network": [] }
}

Detail Levels

minimal
~200-500Landmarks + interactive elements only
summary
~500-1500Adds content summaries, forms, errors
full
variableIncludes all visible text content

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

30 Tools, 6 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

9

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

clicktypeselecttogglesubmitscrollhoverkeywait_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

1

Execute arbitrary JavaScript in page context. Read computed values, trigger events.

evaluate

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. Requires Node.js >= 22 and npm.

1Install & Build

bash
git clone https://github.com/TickTockBent/charlotte.git
cd charlotte
npm install
npm run build

2Configure Your MCP Client

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

.mcp.json
{
  "mcpServers": {
    "charlotte": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/charlotte/dist/index.js"],
      "env": {}
    }
  }
}

Claude Desktop — add to claude_desktop_config.json:

claude_desktop_config.json
{
  "mcpServers": {
    "charlotte": {
      "command": "node",
      "args": ["/path/to/charlotte/dist/index.js"]
    }
  }
}

3Verify It Works

verification
navigate({ url: "https://example.com" })
// Returns: title "Example Domain", landmarks, headings, 1 link

observe({ detail: "minimal" })
// Returns: landmarks + interactive elements only

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.