mcpField
C
Charlotte

Charlotte

本地服务
github.com/TickTockBent浏览器自动化1836 天前更新

关于 Charlotte

Charlotte 是一个 MCP 服务,使用无头 Chromium 将网页渲染为结构化、便于 Agent 读取的表示。它面向需要控制 token 消耗的 AI Agent,按需返回页面摘要与元素信息。

主要功能

  1. 01紧凑的页面概览,按需查询细节
  2. 02基于无障碍树与布局信息的结构化表示
  3. 03提供 43 个工具,支持多种加载配置
  4. 04支持 iframe 与交互操作
  5. 05内置开发审计工具(dev_audit)

适用场景

  1. 01让 AI Agent 浏览网页并查找特定链接或按钮
  2. 02减少每次调用的上下文与 token 开销
  3. 03在本地或远程环境中运行浏览器自动化

MCP 相关

该项目是一个 MCP 服务,通过 stdio 或远程连接向 MCP 客户端提供导航、观察、交互和监控等工具。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"charlotte": {
"command": "npx",
"args": [
"-y",
"@ticktockbent/charlotte"
]
}
}
}
启动命令npx -y @ticktockbent/charlotte

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@ticktockbent/charlotte0.1.3

工具

23

收录的工具列表 · 更新于 3 周前

参数类型必填说明
urlstring是要导航到的 URL
wait_forenum否等待条件:"load"(默认)、"domcontentloaded"、"networkidle"。注意:对于存在持久 WebSocket 连接的 SPA,"networkidle" 不可靠。load | domcontentloaded | networkidle
timeoutnumber否最长等待时间,单位为毫秒(默认值:30000)
detailenum否"minimal"(默认)、"summary"(包含内容上下文)、"full"(包含所有文本内容)minimal | summary | full

详细介绍

Charlotte

让 Web 清晰易读。

你的 AI Agent 只是查看 Hacker News 首页,就要消耗约 50,000 个字符的无障碍树。Charlotte 只需 364 个字符。

Charlotte 是一款 MCP 服务,可为 AI Agent 提供结构化、节省令牌的 Web 访问方式。 Charlotte 不会在每次调用时都倾倒完整的无障碍树,而只返回 Agent 所需的内容:页面加载时提供精简的页面概览,针对特定元素提供定向查询, 仅在明确请求时才提供完整详情。对于内容丰富的页面,这种概览比 Playwright MCP 提供的完整无障碍树快照最多精简约 140 倍;对于极其简单的页面,两者的大小则大致相同。

为什么选择 Charlotte?

大多数浏览器 MCP 服务都会在每次调用时倾倒整个无障碍树——一大段纯文本,在内容丰富的页面上可能超过一百万个字符。无论 Agent 是否需要,都得为全部内容付费。

Charlotte 会将每个页面分解为类型化的结构化表示——地标、标题、交互元素、表单、内容摘要——并通过三种详细程度让 Agent 控制接收内容的多少。当 Agent 导航到新页面时,它会获得精简的页面概览(Hacker News 首页仅 364 个字符),而非完整的元素信息(约 50,000 个字符)。需要具体信息时,再按需查询。

基准测试

在真实网站上,以每次工具调用返回的字符数为指标,使用 Charlotte v0.8.0 与 Playwright MCP v0.0.79 进行测量(npx tsx benchmarks/run-benchmarks.ts --suite comparison),日期为 2026-08-08。本节为摘要——权威基准测试页面(包括各任务成本和版本发布差异)见 charlotte.mintlify.site/benchmarks;方法、测量工具和原始结果见:benchmarks/。

页面导览成本(Agent 到达页面时为“查看”页面付出的成本):

默认情况下,Charlotte 的 navigate 会返回可用的页面导览信息,包括地标、标题,以及按页面区域分组的交互元素数量。使用 Playwright MCP 获取等效信息时,Agent 会调用 browser_snapshot,它会返回完整的无障碍树。(Playwright 的 browser_navigate 单独使用时只会返回简短确认信息,而非页面内容,因此不能进行同类比较。)

网站Charlotte navigatePlaywright browser_snapshot缩减倍数
example.com4154651.1x
httpbin 表单6191,8473.0x
GitHub 仓库3,77838,98310x
Wikipedia(AI 文章)22,1341,137,92851x
Hacker News36450,706139x

页面越复杂,优势越明显:在内容密集型页面上,结构化导览比完整快照小约 10–140 倍;而在 example.com 这样极其简单的页面上,两者相差不到约 20%(对于这么小的页面,结构化表示甚至可能更大——因为根本没有可供精简的内容)。Charlotte 的价值恰恰体现在 Playwright 的扁平转储最不实用的场景中。当 Agent 需要的不仅仅是导览信息时,它会调用 observe 或 find,仅获取所需部分,而不必预先为整棵树付出成本。

工具定义开销(每次 API 调用中不可见的成本):

配置工具数每次调用的定义令牌数相比完整配置节省
full438,500—
browse(默认)234,372约 49%
core72,186约 75%

每次 API 往返都会发送工具定义。使用默认的 browse 配置时,Charlotte 的定义开销比加载全部 43 个工具少约 49%;最精简的 core 配置则可减少约 75%。完整结果见配置基准测试报告。

工作流差异: 每次查看 Hacker News 时,读取完整快照的 Playwright Agent 都会收到约 50,000 个字符,无论它是在阅读头条,还是在查找登录按钮。Charlotte Agent 到达页面时只会收到 364 个字符,随后调用 find({ type: "link", text: "login" }) 精确获取所需内容,无需为其余内容付出成本。

工作原理

Charlotte 会维持一个持久的无头 Chromium 会话,充当视觉网页与 Agent 基于文本的推理之间的转换层。每个页面都会被拆解为结构化表示:

┌─────────────┐     MCP Protocol     ┌──────────────────┐
│   AI Agent  │<────────────────────>│    Charlotte     │
└─────────────┘                      │                  │
                                     │  ┌────────────┐  │
                                     │  │  Renderer  │  │
                                     │  │  Pipeline  │  │
                                     │  └─────┬──────┘  │
                                     │        │         │
                                     │  ┌─────▼──────┐  │
                                     │  │  Headless  │  │
                                     │  │  Chromium  │  │
                                     │  └────────────┘  │
                                     └──────────────────┘

Agent 会收到地标、标题、带类型元数据的交互元素、边界框、表单结构和内容摘要——这些信息均来自浏览器对每个页面已有的了解。

功能

导航 — navigate、back、forward、reload

观察 — observe(3 种详细级别,结构化树视图)、find(空间 + 语义搜索、CSS 选择器模式、大量结果集可使用 output_file)、screenshot(支持持久化的产物管理)、screenshots、screenshot_get、screenshot_delete、diff(与快照进行结构化比较)

交互(支持 iframe)— click、click_at(基于坐标)、type(支持慢速输入)、select、toggle、submit、scroll、hover、drag、key(单个按键 / 按键序列,可指定目标元素)、wait_for(异步条件轮询)、upload(文件输入)、fill_form(批量填写表单)、dialog(接受 / 关闭 JS 对话框)

监控 — console(所有严重级别、筛选、时间戳)、requests(完整 HTTP 历史记录,可按方法 / 状态 / 资源类型筛选)

会话管理 — tabs、tab_open、tab_switch、tab_close、viewport(通用预设或带有 DPR、触控和用户代理模拟的命名设备,例如 “iPhone 15”)、network(限速、URL 屏蔽)、set_cookies、get_cookies、clear_cookies、set_headers、configure

开发模式 — dev_serve(静态服务 + 文件监视并自动重新加载)、dev_inject(注入 CSS/JS)、dev_audit(无障碍、性能、SEO、对比度、失效链接)

实用工具 — evaluate(在页面上下文中执行任意 JS)

工具配置集

Charlotte 提供 43 个工具(42 个已注册工具 + charlotte_tools 元工具),但大多数工作流只需其中一部分。启动配置集可控制加载到 Agent 上下文中的工具,将定义开销最多降低约 75%。

charlotte --profile browse    # 23 tools (default) — navigate, observe, interact, tabs
charlotte --profile core      # 7 tools — navigate, observe, find, click, type, submit
charlotte --profile full      # 43 tools — everything
charlotte --profile interact  # 31 tools — full interaction + dialog + evaluate
charlotte --profile develop   # 34 tools — interact + dev_serve, dev_inject, dev_audit
charlotte --profile audit     # 14 tools — navigation + observation + dev_audit + viewport

Agent 无需重启,即可在会话期间启用更多工具:

charlotte_tools enable dev_mode    → activates dev_serve, dev_audit, dev_inject
charlotte_tools disable dev_mode   → deactivates them
charlotte_tools list               → see what's loaded

自托管(Charlotte 远程版)

将 Charlotte 作为远程 MCP 服务运行,并连接到 claude.ai——只需一条命令:

docker run --cap-add SYS_ADMIN --shm-size 2g -p 3737:3737 ghcr.io/ticktockbent/charlotte

它会打印一个公开连接器 URL 和一个操作员令牌。在 claude.ai 中: 设置 → 连接器 → 添加自定义连接器——粘贴 URL,将 OAuth Client ID/Secret 字段留空,并在 Charlotte 的授权页面出现时输入令牌。就这么简单;现在即可浏览。

演示 URL 和令牌均为临时内容(重启后都会轮换)。如需正式运行——稳定域名、自己的隧道或反向代理、docker compose: 自托管。信任模型和 网络防护:安全。容器 和沙箱内部机制:Docker。

快速开始

前提条件
  • Node.js >= 20
  • npm
安装

Charlotte 已列入 MCP 注册表,名称为 io.github.TickTockBent/charlotte,并以 @ticktockbent/charlotte 发布在 npm 上:

npm install -g @ticktockbent/charlotte

Docker 镜像可从 Docker Hub 和 GitHub 容器注册表获取:

# Alpine (default, smaller)
docker pull ticktockbent/charlotte:alpine

# Debian (if you need glibc compatibility)
docker pull ticktockbent/charlotte:debian

# Or from GHCR
docker pull ghcr.io/ticktockbent/charlotte:latest

也可以从源代码安装:

git clone https://github.com/ticktockbent/charlotte.git
cd charlotte
npm install
npm run build
运行

Charlotte 使用 MCP 协议通过 stdio 通信:

# If installed globally (default browse profile)
charlotte

# With a specific profile
charlotte --profile core

# If installed from source
npm start
MCP 客户端配置
Claude Code

在项目根目录中创建 .mcp.json:

{
  "mcpServers": {
    "charlotte": {
      "type": "stdio",
      "command": "npx",
      "args": ["@ticktockbent/charlotte"],
      "env": {}
    }
  }
}
Claude Desktop

添加到 claude_desktop_config.json:

{
  "mcpServers": {
    "charlotte": {
      "command": "npx",
      "args": ["@ticktockbent/charlotte"]
    }
  }
}
Cursor

添加到 .cursor/mcp.json:

{
  "mcpServers": {
    "charlotte": {
      "command": "npx",
      "args": ["@ticktockbent/charlotte"]
    }
  }
}
Windsurf

添加到 ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "charlotte": {
      "command": "npx",
      "args": ["@ticktockbent/charlotte"]
    }
  }
}
VS Code(Copilot)

添加到 .vscode/mcp.json:

{
  "servers": {
    "charlotte": {
      "type": "stdio",
      "command": "npx",
      "args": ["@ticktockbent/charlotte"]
    }
  }
}
Cline

添加到 Cline MCP 设置中(通过 Cline 侧边栏 > MCP 服务 > 配置):

{
  "mcpServers": {
    "charlotte": {
      "command": "npx",
      "args": ["@ticktockbent/charlotte"]
    }
  }
}
Amp

添加到 ~/.amp/settings.json:

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

请参阅 docs-internal/mcp-setup.md 获取完整设置指南,其中包括开发模式、通用 MCP 客户端、验证步骤和故障排除。

配置

Charlotte 按优先级从高到低从四个来源解析设置:CLI 参数 → 环境变量 → 配置文件 → 内置默认值。完整参考请参阅 docs/configuration.md。

配置文件

使用 --config 指定 JSON 配置文件,或将 charlotte.config.json 放在工作目录中,Charlotte 会自动加载:

charlotte --config charlotte.config.json
{
  "browser": { "headless": true, "noSandbox": false },
  "tools": { "profile": "browse" },
  "rendering": { "includeIframes": false, "iframeDepth": 3 },
  "output": { "dir": "./charlotte-output" },
  "limits": {
    "maxInteractiveElements": 2000,
    "maxFullContentChars": 200000,
    "maxResponseBytes": 1000000,
    "maxEvaluateBytes": 256000
  }
}

所有部分均为可选;空的 {} 也有效。配置文件使用 zod 验证——遇到未知键、类型错误或无效的枚举值时,会在 stderr 上输出清晰的启动错误,且 Charlotte 会以非零状态退出。四项设置也支持通过环境变量配置:CHARLOTTE_NO_SANDBOX、CHARLOTTE_OUTPUT_DIR、CHARLOTTE_CDP_ENDPOINT 和 CHARLOTTE_INIT_SCRIPT。应在每个新文档中、页面 JS 运行前执行的脚本,可放在 browser.initScripts 中,或通过 --init-script <path> 指定(可重复使用);请参阅初始化脚本。

Chromium 沙箱默认开启

**v0.7.0 行为变更:**此前的版本会在每次启动 Chromium 时加入 --no-sandbox。从 v0.7.0 开始,Chromium 沙箱默认启用——它是阻止不可信页面访问 Charlotte 运行所用账户的首要防线。如果内核沙箱不可用,必须明确选择退出。

charlotte --no-sandbox                  # CLI flag
CHARLOTTE_NO_SANDBOX=1 charlotte        # environment variable
# or "browser": { "noSandbox": true }   in the config file

迁移说明(Docker / 裸机):容器通常无法设置内核沙箱,因此提供的 Dockerfile 会为你设置 CHARLOTTE_NO_SANDBOX=1,而 docker-compose.yml 现在会保留 Docker 的默认 seccomp 过滤器(不再使用 seccomp=unconfined 运行)。如果你以 root 身份在裸机上运行 Charlotte,Chromium 会拒绝在启用沙箱的情况下启动——请使用非 root 用户运行(推荐),或传入 --no-sandbox。如果现有配置此前依赖隐式启用 --no-sandbox,且运行环境无法初始化沙箱,则现在必须设置 CHARLOTTE_NO_SANDBOX=1(或使用等效的标志/配置),才能继续正常运行。

通过网络运行 Charlotte Remote(HTTP 模式)还会带来沙箱之外的其他信任边界和网络防护问题——请参阅安全性。

输出大小限制

limits.* 键会限制单个工具响应的返回量,避免异常页面(10 万个链接、无限滚动信息流、巨大的文档正文)撑满 Agent 的上下文窗口。当页面响应超过 maxResponseBytes 时,会降级为精简摘要,并建议通过 output_file 将完整结果写入磁盘;charlotte_evaluate 的结果则由 maxEvaluateBytes 单独限制。被截断的响应会带有 truncation 标记。有关配置项和默认值,请参阅 docs/configuration.md。

崩溃恢复

Chromium 崩溃后不再会导致服务卡死。下一次工具调用会自动重新启动浏览器、清除已失效的标签页和 CDP 会话缓存,并打开一个新的空白标签页——因此,即使渲染进程崩溃,Agent 也能继续工作,无需重启 MCP 服务。

使用示例

连接后,Agent 可以使用 Charlotte 的工具:

浏览网站
navigate({ url: "https://example.com" })
// → 612 chars: landmarks, headings, interactive element counts

find({ type: "link", text: "More information" })
// → just the matching element with its ID

click({ element_id: "lnk-a3f1c2" })
填写表单
navigate({ url: "https://httpbin.org/forms/post" })
find({ type: "text_input" })
type({ element_id: "inp-c7e29b", text: "[email protected]" })
select({ element_id: "sel-e8a3f5", value: "option-2" })
submit({ form_id: "frm-b1d4e7" })
本地开发反馈循环
dev_serve({ path: "./my-site", watch: true })
observe({ detail: "full" })
dev_audit({ checks: ["a11y", "contrast"] })
dev_inject({ css: "body { font-size: 18px; }" })

页面表示

Charlotte 会返回结构化表示,并提供三个详细程度,让 Agent 控制上下文占用量:

最简(navigate 的默认级别)

按页面区域分组的地标、标题和交互元素数量。旨在帮助了解页面概况——“此页面上有什么?”——而不列出每个元素。

{
  "url": "https://news.ycombinator.com",
  "title": "Hacker News",
  "viewport": { "width": 1280, "height": 720 },
  "structure": {
    "headings": [{ "level": 1, "text": "Hacker News", "id": "hdg-a1b2c3" }]
  },
  "interactive_summary": {
    "total": 93,
    "by_landmark": {
      "(page root)": { "link": 91, "text_input": 1, "button": 1 }
    }
  }
}
摘要(observe 的默认级别)

包含类型化元数据、表单结构和内容摘要的完整交互元素列表。

{
  "url": "https://example.com/dashboard",
  "title": "Dashboard",
  "viewport": { "width": 1280, "height": 720 },
  "structure": {
    "landmarks": [
      { "id": "rgn-b2c1d0", "role": "banner", "label": "Site header", "bounds": { "x": 0, "y": 0, "w": 1280, "h": 64 } },
      { "id": "rgn-d4e5f6", "role": "main", "label": "Content", "bounds": { "x": 240, "y": 64, "w": 1040, "h": 656 } }
    ],
    "headings": [{ "level": 1, "text": "Dashboard", "id": "hdg-1a2b3c" }],
    "content_summary": "main: 2 headings, 5 links, 1 form"
  },
  "interactive": [
    {
      "id": "btn-a3f1c2",
      "type": "button",
      "label": "Create Project",
      "bounds": { "x": 960, "y": 80, "w": 160, "h": 40 },
      "state": {}
    }
  ],
  "forms": []
}
完整

包含摘要级别的所有内容,以及页面上全部可见文本。

详细级别

级别令牌数使用场景
minimal~50-200导航后的概览。有哪些区域?有多少个交互元素?
summary~500-5000操作页面。完整的元素列表、表单结构、内容摘要。
full不定阅读页面内容。包含所有可见文本。

导航工具默认使用 minimal。observe 工具默认使用 summary。两者都接受可选的 detail 参数进行覆盖。

元素 ID

元素 ID 在小幅 DOM 变动后仍保持稳定。它们通过对元素类型、ARIA 角色、可访问名称和 DOM 路径签名组成的复合键进行哈希生成:

btn-a3f1c2  (button)    inp-c7e29b  (text input)
lnk-d4b910  (link)      sel-e8a3f5  (select)
chk-f1a204  (checkbox)  frm-b1d4e7  (form)
rgn-e0d2a8  (landmark)  hdg-0f4063  (heading)
dom-b2c3d9  (DOM element, from CSS selector queries)

**v0.7.0 ID 格式变更:**元素 ID 哈希现在为 6 个十六进制字符(例如 btn-a3f1c2),此前版本为 4 个。这大幅减少了大型页面上的跨元素哈希冲突。硬编码 4 字符 ID 或按其模式匹配的 Agent 应重新使用 find 查找元素,而不是在升级后重用缓存的 ID。

ID 在无关的 DOM 变更以及同一容器内的元素重新排序后仍然有效。当 Agent 以最简详细级别导航(不包含单个元素 ID)时,会使用 find 按文本、类型或空间位置查找元素——返回的元素包含可直接用于交互的 ID。

开发

# Run in watch mode
npm run dev

# Run all tests
npm test

# Run only unit tests
npm run test:unit

# Run only integration tests
npm run test:integration

# Type check
npx tsc --noEmit
项目结构
src/
  browser/          # Puppeteer lifecycle, tab management, CDP sessions
  renderer/         # Accessibility tree extraction, layout, content, element IDs
  state/            # Snapshot store, structural differ
  tools/            # MCP tool definitions (navigation, observation, interaction, session, dev-mode)
  dev/              # Static server, file watcher, auditor
  types/            # TypeScript interfaces
  utils/            # Logger, hash, wait utilities
tests/
  unit/             # Fast tests with mocks
  integration/      # Full Puppeteer tests against fixture HTML
  fixtures/pages/   # Test HTML files
架构

渲染器流水线是核心——它按顺序调用提取器并组装 PageRepresentation:

  1. 提取无障碍树(CDP Accessibility.getFullAXTree)
  2. 提取布局(CDP DOM.getBoxModel)
  3. 提取地标、标题、交互元素和内容
  4. 生成元素 ID(基于哈希,在重新渲染后保持稳定)

所有工具都通过 renderActivePage() 调用,该函数负责处理快照、重新加载事件、对话框检测和响应格式化。

沙盒

Charlotte 在 tests/sandbox/ 中包含一个测试网站,可用于测试所有工具,而无需访问公共互联网。使用以下命令在本地提供该网站:

dev_serve({ path: "tests/sandbox" })

五个页面涵盖导航、表单、交互元素、弹出窗口、延迟加载内容、滚动容器等。完整的页面参考和逐工具测试清单,请参阅 docs-internal/sandbox.md。

已知问题

Shadow DOM — 开放的 Shadow DOM 可以透明地正常工作。Chromium 的无障碍树会穿透开放的 shadow 边界,因此 Web 组件(例如 GitHub 的 <relative-time>、<tool-tip>)无需特殊处理,就能将其内容渲染到 Charlotte 的表示中。无障碍树无法访问封闭的 shadow root,因此不会捕获其中的内容。

路线图

会话与配置
功能路线图

视频录制 — 将交互录制为视频,捕获 Agent 驱动的导航和操作的完整过程,用于调试、文档记录和审查。

与 Playwright MCP 的完整差距分析(包括优先级较低的项目:视觉工具、测试/验证、跟踪、传输、安全,以及 Charlotte 的优势领域),请参阅 docs-internal/playwright-mcp-gap-analysis.md。

完整规范

完整规范包括所有工具参数、页面表示格式、元素身份策略和架构详情,请参阅 docs-internal/CHARLOTTE_SPEC.md。

许可证

MIT

社区

  • 对于可复现的缺陷、回归问题或特定于 MCP 客户端的问题,请提交缺陷报告。
  • 对于工作流改进或新功能,请提交功能请求。
  • 如果想提议新增工具、参数接口或配置档案,请提交工具请求。
  • 浏览未解决的问题,了解当前工作和讨论。
  • 查看计划中的适合新手的问题筛选,维护者会为适合入门的任务添加标签。

贡献

请参阅 CONTRIBUTING.md 了解贡献指南。

贡献者

感谢所有为 Charlotte 做出贡献的人!请参阅 CONTRIBUTORS.md。


这是不断扩展的文学主题命名 MCP 服务套件的一部分。更多信息请访问 github.com/TickTockBent。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。