Skip to main content
Glama
TrueNix
by TrueNix

kitesurf-bridge

从任何地方驱动 Cloudflare Kitesurf —— 一个在 Cloudflare Workers 的 V8 隔离环境中运行的、以代理为先的浏览器。零依赖,无需本地 Chrome。

提供四种使用同一引擎的方式:

使用方式

安装

用途

MCP 服务器

npx -y github:TrueNix/kitesurf-bridge mcp

Claude Code、Cursor、Codex、任何 MCP 客户端

CLI

npx -y github:TrueNix/kitesurf-bridge markdown <url>

shell、脚本、CI

库

import { withSession } from 'kitesurf-bridge'

你自己的 Node 代码

DSH / Cordis 插件

组合行

DSH 环境中的原生工具

下面的安装命令使用 GitHub 规范,目前无需注册账户即可使用。一旦发布到 npm 作为 @truenix/kitesurf-bridge,所有 github:TrueNix/kitesurf-bridge 都会缩短为 @truenix/kitesurf-bridge。

npx -y github:TrueNix/kitesurf-bridge markdown https://news.ycombinator.com

这会在 Cloudflare 网络上,用真实的浏览器引擎渲染真实页面,无需本地安装浏览器,也无需 API 令牌。


为什么存在

Kitesurf 不是开源的,无法在你的机器上运行。Cloudflare 表示他们打算“一旦准备好”就将其开源,即便如此,所述目标也是让客户*“在自己的账户上部署自己的 Kitesurf 版本”*——仍然在 Workers 上。

开发循环中也没有本地 Kitesurf:wrangler dev 启动的是你的本地 Chrome,而不是 Kitesurf。Kitesurf 只存在于远程端点上的 browser=kitesurf 后面。

所以实际的问题不是“我能在本地运行它吗”,而是“我能从本地代码驱动它吗”。这个包就是那座桥梁。

安装

作为 MCP 服务器

claude mcp add kitesurf -- npx -y github:TrueNix/kitesurf-bridge mcp
{
  "mcpServers": {
    "kitesurf": {
      "command": "npx",
      "args": ["-y", "github:TrueNix/kitesurf-bridge", "mcp"]
    }
  }
}
{
  "mcpServers": {
    "kitesurf": {
      "command": "npx",
      "args": ["-y", "github:TrueNix/kitesurf-bridge", "mcp"],
      "env": {
        "CLOUDFLARE_ACCOUNT_ID": "your-account-id",
        "CLOUDFLARE_API_TOKEN": "your-browser-run-token"
      }
    }
  }
}

暴露的工具:kitesurf_markdown、kitesurf_text、kitesurf_html、kitesurf_links、kitesurf_screenshot、kitesurf_evaluate、kitesurf_accessibility_tree、kitesurf_probe。

作为 DSH / Cordis 插件

# in an agent preset composition
- '@truenix/kitesurf-bridge/cordis':
    cli: npx -y github:TrueNix/kitesurf-bridge
    timeoutMs: 120000

该插件在主机上注册相同的工具。它特意通过 shell 调用 CLI:动态 Cordis 主机半部分没有 WebSocket、fetch 或 node:* 访问权限,因此无法在沙箱内打开 CDP。参见 cordis/plugin.mjs。

作为库

npm install github:TrueNix/kitesurf-bridge
import { withSession } from '@truenix/kitesurf-bridge';

const md = await withSession({}, async (session) => {
  await session.navigate('https://example.com');
  return session.markdown();
});

CLI

kitesurf-bridge <command> [options]

  markdown <url>     Extract the page as Markdown (main content by default)
  text <url>         Visible text only
  html <url>         Full serialized DOM after JS runs
  links <url>        Every anchor as JSON
  screenshot <url>   PNG/JPEG   (-o file, --full)
  pdf <url>          PDF        (-o file)
  a11y <url>         Filtered accessibility tree
  eval <url> <expr>  Evaluate JS in the page
  probe              Endpoint + engine capability report
  mcp                Run as an MCP server on stdio

有用的选项:--main、--raw、--full、--width、--height、--json、--endpoint、--account、--token、--timeout。

端点

游乐场(默认)

账户

URL

wss://kitesurf.cloudflare.app/devtools/page/kitesurf

wss://api.cloudflare.com/.../devtools/browser?browser=kitesurf

认证

无

Authorization: Bearer <token>

目标

页面

浏览器(自动创建并附加一个页面)

适用场景

评估

生产

设置 CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKEN(或 CF_*)以切换。提供账户 ID 但未提供令牌会直接报错,而不是静默降级到共享游乐场。

[!WARNING] 游乐场是一个免费、共享、未认证的资源,没有 SLA。适合评估和本地代理工作——不要在其上构建生产环境。

关于 Kitesurf 值得了解的事情

这些是针对实时服务验证过的,不是从文档中复制的。kitesurf-bridge probe 可以重现它们。

Kitesurf 不使用 V8 运行页面脚本——它运行 Boa,一个 Rust 编写的 JS 引擎。 Boa 强制更低的递归限制,并抛出 RuntimeLimit: exceeded maximum number of recursive calls。自然的递归 DOM 遍历在任何大型页面(如 Wikipedia、文档站点)上都会失败。因此,这个包的 Markdown 转换器使用显式栈遍历 DOM,将 JS 调用深度保持在 O(1)。如果你使用 kitesurf_evaluate,请优先使用迭代表达式。

导航失败以 Cloudflare 边缘状态码的形式出现,而不是 CDP 错误。 Page.navigate 即使对于不存在的主机也会返回正常的 frameId/loaderId,并且不会触发 Network.loadingFailed。缺失的域名显示为 HTTP 530,损坏的源显示为 520,留下一个约 16 字符的占位文档。信任 Page.navigate 会让代理拿到一个空白页面并称之为成功——因此这个包从 Network 域分类结果,并在 >=400 状态码伴随空文档时抛出异常,同时仍然返回具有可读内容的真实错误页面(带有 status)。

能力标志(已验证):

✅ canvas2d、WebAssembly、shadow DOM、localStorage、cookies、fetch/XHR、IntersectionObserver、MutationObserver

❌ WebGL、ServiceWorker、视频/音频播放、真实的 TLS 指纹机器人挑战握手、长期有效的认证会话

对于这些,请改用 Browser Run 的默认 Chromium 浏览器。

性能权衡(Cloudflare 自己的数据):Kitesurf 比热 Chromium 少用 3–7 倍的 CPU 和内存,但墙钟时间慢 1.7–1.8 倍。这个优势体现在 Cloudflare 的账单上,适用于突发性云代理工作负载——在你自己的硬件上没有任何节省。如果你只是想要本地浏览器自动化,并且已经有 Chrome,那么本地 Playwright 更快,并且支持 WebGL 和视频。

零依赖

package.json 有一个空的 dependencies 块,包括 WebSocket 传输。

Node 的全局 WebSocket(WHATWG)无法发送请求头,而账户端点需要 Authorization: Bearer …。undici 不能作为独立模块导入。因此,src/ws.mjs 直接在 node:http(s) 上实现了 RFC 6455 客户端——握手、掩码、延续片段、64 位长度、ping/pong、关闭——这是 CDP 所需的一切,并支持请求头。

测试

npm test                        # live tests against the playground
KITESURF_SKIP_NETWORK=1 npm test   # offline only

该测试套件特意针对真实服务:有趣的失败(Boa 的递归限制、管道截断、边缘状态码)只会在真实环境中出现。

要求

Node ≥ 18。无需浏览器、无需 API 令牌、无需构建步骤。

许可证

MIT

Maintenance

ActivityMaintained
ResponsivenessSyncing

Related MCP Connectors