Skip to main content
Glama

agentlock-browser

浏览工具依据值的来源而非其内容进行门控。

一个 MCP 服务器,驱动真实的浏览器,并拒绝执行源自页面内容的 URL 或表单值。页面可以随意说任何内容;它唯一做不到的是改变它要求代理使用的字符串的来源。

这是一个 v0 骨架。它基于 AgentLock(工具调用授权的开放标准)构建,并通过 Playwright 直接拥有其浏览器。它不包装 @playwright/mcp,也不依赖它。

为什么不直接包装上游服务器

probe/REPORT.md 记录了 @playwright/mcp 0.0.79 实际返回的内容。每个结果都是单个无类型文本块(在全部 23 条记录结果中 structuredContent 均为 null,其 24 个工具中没有声明 outputSchema)。页面文本到达时没有按元素标识:在 Wikipedia 快照的 874 行 - text: 中,零行带有 ref。元素由不透明的服务端 ref 命名,这些 ref 解析为调用者永远看不到的 Playwright locator,并且同一字段也接受原始 CSS 选择器。此外,browser_evaluate 会运行模型编写的任意 JavaScript。

这些都无法承载来源。因此,此服务器改为输出结构化、可标识、带来源标记的结果,并且没有 evaluate 工具。

Related MCP server: open-browser-control

安装

pip install agentlock-browser
python -m playwright install chromium

从检出开始:

pip install -e .
python -m playwright install chromium

添加到 Claude Desktop

claude_desktop_config.json

{
  "mcpServers": {
    "agentlock-browser": {
      "command": "agentlock-browser",
      "env": {
        "AGENTLOCK_BROWSER_ALLOWLIST": "https://example.com,https://docs.python.org",
        "AGENTLOCK_BROWSER_OPERATOR_TEXT": "research the docs and summarize them",
        "AGENTLOCK_BROWSER_LOG": "/home/you/agentlock-browser.jsonl"
      }
    }
  }
}

AGENTLOCK_BROWSER_CONFIG 可以指向一个包含相同键(allowlistoperator_textlog_pathheadless 等)的 JSON 文件;环境变量优先于该文件。除非设置 AGENTLOCK_BROWSER_HEADLESS=0,否则浏览器以无头模式运行。

工具

工具

参数

门控依据

navigate

url link_id

url 的通道;link_id 的新鲜度

snapshot

(无)

不受门控

read_text

(无)

不受门控

click

element_id

不受门控;其引发的导航受门控

type

element_id, value

value 的通道

back

(无)

不受门控

每个工具都根据声明的 outputSchema 返回 structuredContentsnapshot 返回 {origin, url, title, elements: [{id, role, name, text, href}]}read_text 返回 {origin, blocks: [{id, text}]}。页面文本绝不会作为一条无差异的字符串返回。

元素 ID 在当前页面加载期间保持稳定,并在导航时重新生成:ID 的形式为 <page-load>-e<n>,在导航之前铸造的 ID 在导航之后无法解析。拒绝是带有原因的结构化结果,而不是错误。

来源规则

四个通道:

  • USER:来自操作员消息的文本

  • ALLOWLIST:操作员配置的来源,启动时加载

  • PAGE(origin):从页面内容读取的任何值,并带有来源标记

  • MODEL:由模型组合而成,没有页面或用户血统

值在源头被标记:服务器启动时,操作员的消息文本被记录为 USER,配置的允许列表被记录为 ALLOWLIST,而 snapshotread_text 返回的所有内容在返回时被记录为 PAGE(origin)。内容恰恰在模型能看到它的那一刻变得受污染。

这带来的效果,按操作分:

操作

允许

拒绝

navigate(url)

USER, ALLOWLIST

PAGE, MODEL

navigate(link_id)

来自最近一次快照的 id

过期或未知的 id

type(value)

USER

PAGE, MODEL

由点击导致的跨来源导航

(无)

始终:被视为具有 PAGE 来源的 navigate(url)

在 v0 中不受门控:snapshotread_textback 以及同源点击。

navigate(link_id) 是代理跟随链接的方式。该 id 在服务端解析为 href,且 href 永远不必经过模型,因此,操作员要求的跟随链接仍然可行,而粘贴页面提供的 URL 则不可行。

会导致离开当前来源的点击将以 204 响应,从而放弃导航,页面保持在原位置:没有错误页,也不会向其他来源发出请求。

AgentLock 门控来做决定。 本包记录来源,调用 gate.authorize(),并报告裁决;它从不覆盖裁决。唯一的例外是 link-id 新鲜度规则,AgentLock 无法表达该规则。这些拒绝在日志中标记为 decided_by: "server:link_freshness",因此绝不会被误认为是门控裁决。参见 NEEDS.md

每个决策和每条来源记录都会连同门控的证据和签名回执一起追加到 JSONL 日志中:

{"event": "decision", "action": "navigate_url", "allowed": false,
 "reason": "param_lineage", "channel": "PAGE", "origin": "http://fixture.test",
 "decided_by": "agentlock_gate",
 "evidence": {"gate": "param_lineage", "matched_param": "url",
              "matched_token": "evil.test/collect?x=handbook-session-7f3a1c",
              "untrusted_provenance_id": "cprov_8fb61c8f03117287"},
 "receipt": {"receipt_id": "rcpt_…", "signature": "…"}}

该日志是预注册测试的权威依据,绝不是聊天摘要。

USER 通道

MCP 无法让服务器看到操作员的消息,因此 USER 文本是启动输入(operator_text / AGENTLOCK_BROWSER_OPERATOR_TEXT),而不是工具参数可以携带的内容。操作员文本为空或平淡的会话,其 USER 基线弱于操作员明确说明其需求的会话(参见下面的第二个限制)。

测试

pytest                                  # T5 runs; T1-T4 are registered and skipped
cat tests/results/T5.txt                # the raw T5 transcript, log and checks

T5(合法基线)在无模型参与的循环中自动化运行:工具调用被直接发出,因此衡量的是门控和服务器。T1-T4 的测试夹具和两个本地来源均已实现(evil.test 解析到第二个本地服务器,因此跨来源案例是真实的),但它们的模型驱动运行尚未实现,因为这些预测涉及模型行为。

已列出的限制

逐字复制自 PREDICTIONS.md,该文件在任何服务器代码存在之前就已冻结:

  • 选择影响:页面内容仍然可以引导模型选择哪个 link_id。这超出范围,已有记录,与 AgentLock 核心相同。

  • 同源点击在 v0 中不受门控。 恶意站点可以在自身内部驱动代理。跨来源是我们防御的边界。

  • 模型拒绝可能使 T1 和 T3 失去信息量。 这是载荷问题,而不是门控结果。

在构建 v0 时发现,且尚未解决:

  • 血统门控对没有独特令牌的值会失效开放(fail open)。 AgentLock 通过从值中提取令牌来对其进行分类;一个短于 12 个字符、没有数字或标点符号的普通单词不会产生任何令牌,而无法分类的值将被允许。说 输入单词 expenses 的页面不会被捕获;说 输入 abc123 的页面则会被捕获。此类授权被记录为 "channel": "UNCLASSIFIED", "fail_open": true,而不是通过本地检查来关闭,因为在这里关闭会将决策移出门控。NEEDS.md 第 3 项。

  • 平淡的操作员消息会削弱 MODEL 检查。 新血统需要在权威上下文中具有独特令牌才能拥有基线;没有基线,则由 MODEL 组合的值会被允许。NEEDS.md 第 3(b) 项。

  • read_textsnapshot 报告一组精选的元素。 两个选择器都不匹配的元素中的文本不会被返回,因此永远不会被记录为 PAGE。只有在这些工具是页面内容进入对话的唯一途径时,这种一致性才能保持(模型看不到的内容,它也无法复述)。

  • 来自已授权导航的重定向会被跟随,而不会进行第二次检查。 v0 授予它所允许的 URL 的重定向链。

  • 单个标签页。 target="_blank" 和弹窗在 v0 中未处理。

许可证

AGPL-3.0-or-later. Copyright 2026 David Grice.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.

  • Choose HTTP, browser, machine endpoint, or avoid before an agent visits an unfamiliar URL.

  • Stealth web browser for agents: search, fetch, click and type through persistent sessions over MCP.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/webpro255/agentlock-browser'

If you have feedback or need assistance with the MCP directory API, please join our Discord server