10 个关键问题Q&A
-
Q:Jev Browser 和普通浏览器自动化(Playwright)区别在哪? A:Playwright 需要手写选择器;Jev Browser 由 Jev 模型自主识别页面元素、选择动作,只需要给自然语言任务和 URL。 -
Q:Jev 模型会生成输入文本吗? A:不会。Jev 只负责选动作;搜索、表单文字由独立打字模型生成。 -
Q:密码怎么安全填入,会不会被大模型看到? A:密码通过一次性转交文件或指定环境变量传入,限定可信域名,模型全程接触不到明文密码。 -
Q:有哪些接入方式? A:MCP 服务(Stdio/HTTP)、命令行 CLI、Typescript 库导入。 -
Q:可以多人共用一个远程服务吗? A:可以,开启 HTTP 模式,无状态,支持负载均衡,需要配置鉴权 Token。 -
Q:怎么实现登录后直接操作页面? A:两种方案:密码填充、seed cookie 注入,都做脱敏处理。 -
Q:遇到 Cloudflare 人机验证会怎么样? A:自动识别,等待短时间自动放行;无法放行则标记 blocked,停止任务,不再消耗 token。 -
Q:能不能本地跑,不用云端 LLM? A:可以,打字模型配置 Ollama 等本地 OpenAI 兼容端点;Jev 判定本身仍需要对应服务商 API。 -
Q:运行限制有哪些? A:单步最多 240 个元素;不支持 iframe、hover 菜单、ShadowDOM;默认最大 180 秒、最多 24 步。 -
Q:输出结果包含什么? A:目标页面内容(text/markdown/html/aria)、步骤追踪、置信度、token 消耗、预估费用、截图、控制台报错。
说明:技术文档风格,术语统一(MCP、Agent、无头浏览器、Noul、Seed Cookie 等保留 / 加注;代码、命令、链接原样保留) Jev Browser https://github.com/jkudish/jev-browser#jev-browserhttps://github.com/jkudish/jev-browser/actions/workflows/ci.yml https://github.com/jkudish/jev-browser/blob/main/LICENSE https://github.com/jkudish/jev-browser/blob/main/.github/jev-browser-banner.png
基于 TypeSafe Jev 模型打造,快速、低成本实现浏览器自动化。 只需给 Jev Browser 一项任务和一个网址。 它通过 MCP 服务、命令行(CLI)或者代码库驱动真实的无头浏览器。TypeSafe 的 Jev 模型在每一步从页面里可选点击、输入、下拉选择的元素中挑选一个动作,同时评估任务达成概率、任务卡死概率。任务循环逻辑由代码掌控:包含配额、异常恢复、停止判定条件。执行结束后你可以拿到目标页面内容、带置信度的步骤追踪日志、控制台报错以及页面截图。
它已经在真实网站(非演示页面)上实现这些能力:
-
在维基百科从 “咖啡” 词条导航到 “浓缩咖啡” 词条,耗时约 4 秒,成本仅 0.0016 美元 -
填写联系表单并停止,不提交表单 -
从实时定价页面抓取价格 -
将完整文档页面输出为 Markdown -
导出 WordPress 站点的无障碍访问树结构
本项目尚处于早期版本。复杂网站上容易出现兼容性问题。欢迎提交 Issue 和 PR,详见:https://github.com/jkudish/jev-browser/blob/main/CONTRIBUTING.md
演示
https://github.com/jkudish/jev-browser#demo 自动在 GitHub 搜索该仓库、打开 Releases 页面,并回答关于该页面的问题。每一步 Jev 的判断结果都会展示在右侧:选中的动作、置信度、目标达成概率、卡死概率。 演示动图:https://github.com/jkudish/jev-browser/blob/main/assets/github-demo.gif 高清演示视频:https://github.com/jkudish/jev-browser/blob/main/assets/github-demo.mp4
安装
https://github.com/jkudish/jev-browser#install 依赖要求:Node.js 22 及以上版本;Jev 服务传输密钥(默认在 https://console.typesafe.ai/settings/keys 获取,其他备选方案见配置章节);可选:文本输入模型服务商密钥(详见「文本输入模型」章节)。 安装时会自动下载 Playwright 的 Chromium;如需关闭自动下载,设置环境变量 JEV_BROWSER_SKIP_BROWSER_DOWNLOAD=1。
让 AI Agent 帮你自动安装
https://github.com/jkudish/jev-browser#let-an-agent-install-it-for-you 把下面这段提示词粘贴到你的代码 Agent:
帮我安装 Jev Browser 的 MCP 服务。npm 包名为 @jkudish/jev-browser,启动命令 npx -y @jkudish/jev-browser;在你的 MCP 客户端里注册该服务。检查环境里是否已经配置 TYPESAFE_API_KEY;如果没有,请引导我配置密钥,不要直接把密钥粘贴到对话中(密钥可在 console.typesafe.ai/settings/keys 创建)。注册完成后,询问我是否要运行第一个导航任务,运行后展示步骤追踪日志和消耗成本。完整文档:https://github.com/jkudish/jev-browser#readme
通过 npm 直接查看帮助: npx -y @jkudish/jev-browser --help
支持客户端:Amp、Claude Code、Codex(~/.codex/config.toml)、OpenCode(opencode.json)以及其他任意 MCP 客户端。 部分 MCP 客户端在拉起服务前会过滤环境变量,会导致 TYPESAFE_API_KEY 丢失。如果服务提示缺少密钥,按上文方式显式传入。
远程部署 / HTTP 模式
https://github.com/jkudish/jev-browser#remote--http 默认使用标准输入输出(Stdio)模式。如果要给团队或者远程 Agent 共享部署服务,使用无状态 HTTP 模式启动:
JEV_BROWSER_AUTH_TOKEN="$(openssl rand -hex 32)" TYPESAFE_API_KEY=ts_xxx npx -y @jkudish/jev-browser --http
服务监听 PORT端口(默认 8080),MCP 接口地址 /mcp,健康检查接口 /health。HOST默认 127.0.0.1;设置 HOST=0.0.0.0对外提供访问。 --http参数等价于环境变量 JEV_BROWSER_TRANSPORT=http,容器、系统服务可以直接用环境变量配置,不用命令行参数。 服务兼容 MCP 协议版本 2026-07-28,同时向下兼容,为 2025 版客户端提供无状态服务;不保存会话,可在负载均衡后部署多实例副本。 每一次调用都会消耗 Jev 密钥额度、拉起真实浏览器,因此:除非仅本机回环访问,否则必须配置 JEV_BROWSER_AUTH_TOKEN。客户端以 Bearer Token 方式携带鉴权:
claude mcp add --transport http jev-browser https://jev-browser.example.com/mcp --header "Authorization: Bearer $JEV_BROWSER_AUTH_TOKEN"
两个浏览器相关限制决定部署方案:
-
每一个并发调用都会独立拉起无头 Chromium,运行时长不超过 max_seconds(默认 180 秒,上限 600 秒)。并发请求上限由JEV_BROWSER_MAX_CONCURRENCY控制(默认 4),超出直接返回 429。每个实例都需要预留足够内存给浏览器进程。 -
网页导航任务有可能正常运行数分钟。反向代理、负载均衡的读取超时时间,必须大于你设置的最大执行秒数,否则会中断正常任务。客户端 SDK 同样有超时(TS SDK 默认 60 秒),需要同步调高工具调用超时,匹配配额。
服务本身使用纯 HTTP;公网暴露时,在反向代理 / 负载均衡层终止 TLS。在入口处配置连接限制、请求限流。进程会限制 /mcp并发请求,请求体上限 4MiB;但不会限制等待头部、反复被拒绝的连接。 工具列表是静态的:服务不支持 listChanged通知,拒绝 subscriptions/listen订阅请求,空闲的订阅连接不会占用并发槽位。绝大多数不开启订阅的客户端不受影响。
Agent 技能包
https://github.com/jkudish/jev-browser#agent-skill 该包内置一套 Agent 技能(skills/jev-browser/),教会代码 Agent:什么时候调用 jev_navigate,而不是简单静态拉取;如何读取配额、状态、判断追踪日志;如何安全登录,防止密钥泄露。 复制到你的客户端技能目录:
npm pack @jkudish/jev-browser@latest
tar -xzf jkudish-jev-browser-*.tgz
mkdir -p .claude/skills && cp -R package/skills/jev-browser .claude/skills/
Claude Code 读取 .claude/skills;OpenCode 读取 .opencode/skills;Codex 和通用 Agent 读取 .agents/skills。在 Amp 中,技能配置头已经绑定 MCP 服务,放入技能目录即可自动接入。
不使用 MCP:命令行与库调用
https://github.com/jkudish/jev-browser#without-mcp-cli-and-library 同一个 Agent 能力可以直接在命令行运行,结果 JSON 输出到标准输出:
npx -y @jkudish/jev-browser run "Find the newest release and stop on it" https://github.com/jkudish/jev-browser/releases
CLI 参数包含:--format、--max-chars、--max-steps、--max-seconds、--no-typing、--screenshot 图片路径、--record webm路径(也可以指定目录存放 Playwright 原始录屏)、--cookie-file name=@路径用于带会话登录。执行 --help查看完整参数。
两种登录已鉴权页面的方式:密码填充登录(https://github.com/jkudish/jev-browser#password-fill-logins,Agent 不输入文字,由底层代码填入)、种子 Cookie(启动时直接带入登录态)。Agent 本身永远不会向密码输入框打字,二选一即可。 Cookie 的值从文件读取,保证会话令牌不会出现在命令行参数、Shell 历史、进程列表;刻意没有提供 --cookie name=value这种直接传值参数。
npx -y @jkudish/jev-browser run "Open the newest order and stop on it" https://app.example.com/orders \
--cookie-file "session=@$HOME/.cache/example-session"
也可以作为库导入。包导出的 navigate是无副作用函数:导入包本身不会启动服务、拉起浏览器,只有调用时才执行。
import { navigate } from "@jkudish/jev-browser";
const result = await navigate({
task: "Find the price of the Pro plan",
startUrl: "https://example.com/pricing",
format: "markdown",
maxSteps: 16,
cookies: [{ name: "session", value: process.env.EXAMPLE_SESSION }], // 可选种子Cookie
});
if ("error" in result) throw new Error(result.error);
console.log(result.status, result.finalUrl);
console.log(result.page.content);
库模式:自定义判断传输层
https://github.com/jkudish/jev-browser#judgment-transports-in-the-library 内置 Jev 传输后端:TypeSafe、OpenRouter、Cloudflare、Vercel,按顺序读取凭证自动选择。选择逻辑、结果校验封装在共享包 https://github.com/jkudish/jev-agent-tools。 环境变量 JEV_PROVIDER强制指定后端;名称未知、凭证缺失直接报错,不会静默降级。该配置独立于文本输入模型。 库调用方可以自定义传输层,绕过自动服务商检测,同时保留原有文本输入模型配置:
import { navigate, type JevTransport } from "@jkudish/jev-browser";
const transport: JevTransport = {
name: "my-gateway", // 会记录为 jev_provider
async ask({ state, questions, model, signal }) {
const response = await myGateway.decide({ state, questions, model, signal });
return {
answers: response.answers,
usage: { input_tokens: response.inputTokens, output_tokens: response.outputTokens },
model: response.effectiveModel,
};
},
};
const result = await navigate({ task: "Find the price", startUrl: "https://example.com", transport });
ask入参:页面状态、查询问题、指定模型、终止信号。返回必须匹配 Jev 格式,包含所有请求 ID 对应的答案、非负 Token 计数、实际使用模型。动作选择概率分布总和接近 1、必须覆盖全部候选项;Noul 取值范围 [0,1]。返回非法答案会直接终止任务,不执行动作。 est_cost_usd仅为 Jev Token 估算费用,自定义网关的实际账单以此网关为准。
密码填充(登录)
https://github.com/jkudish/jev-browser#password-fill-logins Agent 可以自动填充原生密码框,密码明文永远不会传给大模型。密码通过三种渠道传入,仅在单次任务生命周期驻留内存;任务产生的所有状态、日志、报错、URL、返回载荷都会擦除密码痕迹。 带密码的任务默认禁止录屏;尝试填充密码后,最终截图也会屏蔽(注入页面从一开始就可能展示密码)。密码填充不会自动提交表单:不会自动按回车、自动点击提交按钮。
先在 MCP 服务环境设置可信源锚点:
JEV_BROWSER_PASSWORD_ORIGIN=https://acme.com
必须填写完整源标识(协议、主机、端口),不支持通配符;http 仅允许localhost。密码填充只在该源生效;其他域名填充请求直接拒绝,日志标记 origin_mismatch。
然后为每一次任务注入密钥。任何可以输出字节的密码管理器都支持:1Password、Bitwarden、pass、LastPass、macOS 钥匙串、secret-tool、Vault、普通文件、环境变量。
-
MCP 方式:一次性转交文件 服务只读取放在转交目录(默认 ~/.jev-browser/handoff,权限 0700)内的文件,校验所有者、文件权限 0600、无软链接、大小合法;任务启动后立刻读取并删除文件:
mkdir -p ~/.jev-browser/handoff && chmod 700 ~/.jev-browser/handoff
pwfile="$HOME/.jev-browser/handoff/pw.$$"
op read --no-newline --out-file "$pwfile" 'op://Work/acme/password'
chmod 600 "$pwfile"
// 参数
{
"task": "Log in and open the billing page",
"start_url": "https://acme.com/login",
"password_file": "/home/you/.jev-browser/handoff/pw.12345"
}
-
MCP 方式:环境变量传入 变量名必须以 JEV_PASSWORD_开头才会被识别;其他名称直接拒绝,防止模型探测环境:
# 在MCP服务环境一次性设置
JEV_PASSWORD_ACME="$(op read --no-newline 'op://Work/acme/password')"
// 参数
{
"task": "Log in and open the billing page",
"start_url": "https://acme.com/login",
"password_env": "JEV_PASSWORD_ACME"
}
-
CLI 方式:管道输入 -代表从标准输入读取密码,密码不会留在参数、环境、进程列表:
op read --no-newline 'op://Work/acme/password' |
npx -y @jkudish/jev-browser run "Log in and open the billing page" \
https://acme.com/login --password-file - --password-origin https://acme.com
密码机制规则与限制
password_file仅接受本地文件路径。严禁把密码写在任务描述、工具参数、命令行、文件名中。 -
库调用:在 navigate参数传入password: {value, origin},校验、源绑定、脱敏逻辑完全一致。 -
转交文件是一次性:任务启动读取后删除,每次任务都要重新生成。 -
依赖 Agent Shell 和 MCP 服务共享文件系统;无法防护宿主 Agent 主动读取文件、直接调用密码管理器, op read这类命令应当视为运维可信操作。 -
可信域名页面本身可以读取、提交密码,源绑定不能保证站点本身没有被入侵。 -
脱敏是多层防护:原始值、百分号编码、表单编码、HTML 转义、Markdown 转义、空白归一化、Aria 快照 YAML 里所有密码痕迹全部清除。包含下拉选项、链接、摘要、报错文本在内的所有捕获内容都会按最长密码长度做匹配擦除;下拉框按 DOM 索引选择,不靠文本标签。任务文本在送入模型前就脱敏;就算调用方违规把密码写进任务描述,模型依旧看不到明文。 -
密码包含换行、控制字符,或是归一化后过短,会直接拒绝;请用 op read --no-newline生成合规密码。 -
脱敏无法防御内存嗅探、操作系统级监控、任意数据变换后的泄露。出于同样原因,密码任务禁用 Playwright 调试开关(PWDEBUG、DEBUG、DEBUG_FILE)和录屏。 -
不传入密码时,页面上的密码输入框会直接跳过识别;该特性不启用,没有额外开销。 -
同一次任务所有密码框填入同一个配置密码;该功能用于登录,不是多密码表单填写。设置 allow_typing: false全局关闭密码填充。
种子 Cookie(携带登录态启动)
https://github.com/jkudish/jev-browser#seed-cookies-start-behind-a-login 种子 Cookie 把预先拿到的会话(浏览器配置文件、登录脚本、密码管理器导出)在首次导航前注入浏览器上下文,任务启动直接处于登录状态。密码填充、种子 Cookie 是两种支持的鉴权方案;Agent 不会手动在密码框输入。
Cookie 明文和密码同等级保护:不会进入模型可见参数。CLI 从文件读取(--cookie-file name=@path,可多个);MCP 支持一次性转交文件(cookie_file)和 JEV_COOKIE_*环境变量(cookie_env),和密码的引用式交付逻辑一致。库调用在 navigate传入 cookies: [{name, value}],格式同密码。 所有 Cookie 值在模型可见状态、日志、报错、控制台事件、返回载荷里脱敏;多个 Cookie + 密码时,按最长字符串优先擦除。 种子 Cookie 任务禁止录屏、截图屏蔽:页面首帧就可能包含 Cookie 对应的身份信息,视频帧无法脱敏。 不支持和外部传入的 page 对象同时使用:addCookies会篡改外部应用持有的浏览器上下文。 Cookie 值校验规则同密码:空值、超过 4096 字节、少于 4 字符、带控制字符直接拒绝,这类内容无法可靠脱敏。
仅传入 name 和 value 时,Cookie 默认属性:
|
|
|
|
|---|---|---|
|
|
|
.example.com;__Host-前缀 Cookie 强制仅主机,填 domain 会报错
|
|
|
|
__Host-前缀 Cookie 强制 path=/
|
|
|
|
__Host-、__Secure-前缀 Cookie 强制 secure=true,无法关闭
|
以下略。。。

