mcpField
W
Web Speed

Web Speed

本地服务
github.com/Dominic-Pi-Sunyer浏览器自动化112 天前更新

关于 Web Speed

Web Speed 是供 Agent 使用的网页结构化 MCP 服务,可将网页转为包含标题、链接、表单和表格的地图,不依赖 LLM 处理内容。它还可抓取站点页面并分类,帮助 Agent 规划网页交互。

主要功能

  1. 01提取网页结构化地图
  2. 02提交表单并解析结果页
  3. 03抓取站点并生成页面地图
  4. 04按 CSS 选择器检查元素
  5. 05分类页面类型并管理缓存

适用场景

  1. 01从网页提取导航和正文链接
  2. 02规划跨多个页面的操作流程
  3. 03读取表单字段并提交数据
  4. 04检查商品列表或表格中的元素

MCP 相关

Web Speed 通过 MCP 向客户端提供六种网页工具,包括页面解析、表单提交、站点抓取、元素检查、页面分类和缓存失效。

配置

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

mcp.json · 通用配置
{
"mcpServers": {
"web-speed-oss": {
"command": "npx",
"args": [
"-y",
"mcp-remote"
]
}
}
}
启动命令npx -y mcp-remote

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

安装包
npmmcp-remote

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Web Speed

Web Speed 为 AI Agent 解决信噪比问题。现代 Web 面向人类阅读进行了优化(杂乱的 HTML、复杂的布局、以 JS 为主的界面),而 Web Speed 会将这些混乱内容转换为确定性的、高效利用令牌的结构化地图,专为高吞吐量的 Agent 集群而设计。

内部不含 AI。 不依赖 anthropic、openai 或任何大模型。所有解读都由调用它的 Agent 完成。

我们还建议为你选择的大模型设置一个主指令文件(gemini.md、“Claude 指令”等)。此处有一份示例文档。


存在的意义

问题Web Speed 解决方案
原始 HTML 包含超过 150,000 个字符的脚本、样式和 SVG 噪声移除所有非结构化内容 → 最多减少 97% 的令牌用量
大模型会在原始 DOM 中臆造元素 ID,并遗漏交互点返回一份固定的结构化地图——页面上有什么就有什么,不会凭空捏造
自定义爬虫会因网站不同而失效确定性协议——Web 上的所有网站都使用相同的 JSON 结构
Agent 必须每次往返都重新发现页面site_map 可在一次调用中爬取整个域名

工具

工具描述
interpret_page完整的结构化地图:标题、导航、内容链接、表单、表格、文本、元数据
submit_form提交表单(GET 或 POST),并获取提交后页面的地图
site_map从根 URL 开始爬取,并返回所有页面的合并地图
inspect_element获取与 CSS 选择器匹配的节点的详细结构化数据
page_type即时页面分类——login、listing、article、form、navigation、other
invalidate_cache清除缓存的地图,以便下次调用时获取最新内容

安装

Mac / Linux
cd web-interpreter
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Windows
cd web-interpreter
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt

运行

使用 MCP 检查器进行本地开发:

mcp dev server.py

通过 stdio 直接运行(MCP 客户端的启动方式):

python server.py

注册到 Claude / Cowork

将以下内容添加到 ~/Library/Application Support/Claude/claude_desktop_config.json(Mac)或 Windows 上对应的配置文件中:

{
  "mcpServers": {
    "web-speed": {
      "command": "/absolute/path/to/web-interpreter/venv/bin/python",
      "args": ["/absolute/path/to/web-interpreter/server.py"]
    }
  }
}

然后退出并重新启动 Claude Desktop / Cowork。这六个工具将显示在 web-speed MCP 服务下。


读取本地开发服务(可选启用)

默认情况下,Web Speed 会阻止私有地址和环回地址(SSRF 防护),因此访问 http://127.0.0.1:8080 会返回 BLOCKED。如需读取自己的开发服务,请在 WEBSPEED_ALLOW_HOSTS 中列出确切的 host:port 对:

"web-speed": {
  "command": "/absolute/path/to/web-interpreter/venv/bin/python",
  "args": ["/absolute/path/to/web-interpreter/server.py"],
  "env": { "WEBSPEED_ALLOW_HOSTS": "127.0.0.1:8080" }
}
  • 使用逗号分隔;IPv6 地址需加方括号:127.0.0.1:8080,[::1]:3000,localhost:5173。
  • 主机名和端口必须完全匹配。127.0.0.1:8080 不会开放 127.0.0.1:6379 或任何其他地址。
  • 必须始终指定端口,即使是 80 或 443 也不例外。
  • 不支持通配符或 CIDR 范围。格式错误的条目会被忽略,因此拼写错误的地址仍会被阻止。
  • 优先使用字面 IP 地址。添加主机名条目意味着信任该名称解析到的地址。
  • 在服务会获取他人选择的 URL 的任何环境中,都不要设置此项。

测试

venv/bin/python -m unittest discover -s tests

输出架构

interpret_page
{
  "url": "https://example.com/",
  "fetched_at": "2025-01-01T12:00:00Z",
  "page_type": "other",
  "title": "Example Domain",
  "description": "",
  "headings": [
    { "level": 1, "text": "Example Domain" }
  ],
  "navigation": [
    { "label": "Home", "url": "https://example.com/", "location": "header" }
  ],
  "content_links": {
    "total": 47,
    "truncated": false,
    "items": [
      { "label": "More information...", "url": "https://www.iana.org/domains/example" }
    ]
  },
  "forms": [
    {
      "id": "search",
      "action": "https://example.com/search",
      "method": "GET",
      "fields": [
        {
          "name": "q",
          "type": "text",
          "label": "Search",
          "placeholder": "Search...",
          "required": false,
          "value": ""
        },
        {
          "name": "_csrf",
          "type": "hidden",
          "label": "",
          "placeholder": "",
          "required": false,
          "value": "abc123"
        }
      ]
    }
  ],
  "tables": [
    {
      "id": "results",
      "headers": ["Name", "Price", "Stock"],
      "rows": [["Widget A", "$9.99", "In stock"]]
    }
  ],
  "text_blocks": [
    { "tag": "p", "text": "This domain is for use in illustrative examples." }
  ],
  "metadata": {
    "lang": "en",
    "canonical": "",
    "open_graph": { "title": "", "description": "", "image": "" }
  }
}

关键字段:

  • navigation — 语义化 nav/header/footer 元素中的链接(网站框架、菜单)。最多返回 60 个。
  • content_links — 页面主体中的链接(文章、搜索结果、列表)。始终包含 total,因此即使截断到 60 个,也能知道实际数量。
  • forms — 每个表单及其所有字段;CSRF 令牌会在隐藏字段的 value 中原样保留。
  • page_type — 根据结构推断:密码字段 → login;多个条目或链接 → listing;包含段落的 <article> → article;表单 → form;以链接为主 → navigation。

page_type

轻量级工具——只返回分类结果。页面已缓存时可即时返回。

{
  "url": "https://example.com/login",
  "fetched_at": "2025-01-01T12:00:00Z",
  "page_type": "login",
  "title": "Sign In"
}

submit_form

与 interpret_page 输出格式相同,适用于服务器在提交后跳转到的页面。

{
  "url": "https://example.com/login",
  "method": "POST",
  "fields": {
    "email": "[email protected]",
    "password": "hunter2",
    "_csrf": "abc123"
  }
}

CSRF 令牌按原样放入 fields 中——从先前 interpret_page 调用返回的 forms 数组中的隐藏字段提取。


inspect_element

获取匹配 CSS 选择器的节点的深层结构化数据。最多返回 25 个元素。

{
  "url": "https://example.com/shop",
  "selector": ".product-card",
  "matched": 48,
  "truncated": true,
  "elements": [
    {
      "tag": "div",
      "id": "product-42",
      "classes": ["product-card", "featured"],
      "text": "Widget Pro $49.99 Add to cart",
      "attributes": { "id": "product-42" },
      "links": [{ "label": "Add to cart", "url": "https://example.com/cart/add/42" }],
      "fields": [],
      "children": [
        { "tag": "h3", "text": "Widget Pro" },
        { "tag": "span", "text": "$49.99" },
        { "tag": "a", "text": "Add to cart", "href": "https://example.com/cart/add/42" }
      ]
    }
  ]
}

选择器示例:#login-form、.product-card、table.results tbody tr、nav a、[data-testid="price"]


site_map
{
  "root_url": "https://example.com",
  "crawled_at": "2025-01-01T12:00:00Z",
  "total_pages": 8,
  "pages": [
    {
      "url": "https://example.com",
      "title": "Home",
      "page_type": "navigation",
      "depth": 0,
      "links_to": ["https://example.com/about", "https://example.com/contact"]
    }
  ],
  "all_forms": [
    {
      "found_on": "https://example.com/contact",
      "id": "contact",
      "action": "https://example.com/contact/submit",
      "method": "POST",
      "fields": [
        { "name": "email", "type": "email", "label": "Your email", "placeholder": "", "required": true, "value": "" },
        { "name": "message", "type": "textarea", "label": "Message", "placeholder": "", "required": true, "value": "" }
      ]
    }
  ],
  "all_navigation": [
    { "label": "About", "url": "https://example.com/about" },
    { "label": "Contact", "url": "https://example.com/contact" }
  ]
}

invalidate_cache
{ "url": "https://example.com", "invalidated": true }

错误

工具不会抛出异常。发生故障时:

{
  "error": true,
  "code": "FETCH_FAILED | PARSE_FAILED | TIMEOUT | NOT_HTML",
  "message": "human-readable explanation",
  "url": "https://example.com/broken"
}

Agent 应如何使用输出

浏览网站: 查看 navigation 获取网站框架元素(菜单、页眉、页脚),查看 content_links 获取页面正文中的链接。即使列表被截断,content_links.total 也会告知链接总数。选择符合目标的链接,然后调用 interpret_page。

提交表单: 查看 forms。每个字段都包含 name(要发送的内容)、type(预期数据类型)、label/placeholder(字段用途)、required 和 value。隐藏字段(type: "hidden")携带 CSRF 令牌——将其 value 原样传回。构建一个扁平的 name → value 字典,然后调用 submit_form。

提交前先分类: 如果需要分支处理逻辑(例如判断当前页面是登录页还是仪表板),但不想花费完整调用 interpret_page 的成本,请先调用 page_type。

深入查看组件: 在地图中看到表格,但想查看各行?看到商品列表,但想获取每张卡片的链接和价格?调用 inspect_element 并传入 CSS 选择器,即可获取这些特定节点的结构化详情,而无需重新加载整个页面。

预先规划多步骤工作流: 开始前调用 site_map。你会获得每个页面的标题、类型、深度和出站链接,以及网站上的所有表单——无需一次往返,就能规划完整工作流(查找登录表单、查找数据录入页面、查找提交端点)。

page_type 是参考信号,而非保证: 分类结果基于启发式判断。提供空 HTML 外壳的 JavaScript 渲染型 SPA 通常会被归类为 other——密码字段要等 JavaScript 运行后才会出现在 HTML 中。将 page_type 作为快速筛选依据,然后根据实际的 forms 和 headings 进行验证。


共享注册表同步

默认情况下,OSS 服务每次构建新的页面地图时,都会异步提交到 Web Speed 共享注册表 api.getwebspeed.io。这是众包飞轮——每个获取 URL 的 Agent 都会将其加入全局缓存,让世界各地的下一个 Agent 即时获得响应。

此功能默认启用,仅可选择退出。 默认开启是因为贡献者越多,所有 Agent 的运行速度就越快。

共享内容

仅共享页面结构数据:

  • 页面类型、标题、描述
  • 标题、导航链接、内容链接
  • 表单字段名称、类型和标签(不含值)
  • 表格、文本块
  • Open Graph 元数据

绝不共享: Cookie、会话令牌、表单值、JS 渲染的地图(其中可能包含特定会话的登录状态)。

禁用同步

启动服务前设置环境变量:

WEB_SPEED_REGISTRY_SYNC=false python server.py

或在 MCP 客户端配置中设置:

{
  "mcpServers": {
    "web-speed": {
      "command": "/path/to/venv/bin/python",
      "args": ["/path/to/server.py"],
      "env": {
        "WEB_SPEED_REGISTRY_SYNC": "false"
      }
    }
  }
}
指向可自托管的注册表

如果你在运行自己的托管实例,可将同步目标设为该实例:

WEB_SPEED_REGISTRY_URL=https://your-instance.example.com python server.py
同步行为
  • 发出后即不再等待:贡献内容会在后台发送。无论 ping 是否成功,Agent 的请求都会以全速完成。
  • 仅在缓存未命中时同步:本地 24h 磁盘缓存中已有的地图不会重新发送。
  • 故障静默处理:网络错误、超时和服务器拒绝仅记录在 DEBUG 级别,不会反馈给 Agent。

架构

URL  ──▶  fetcher.py         (httpx: 10s timeout, 5 redirects, Chrome UA
                ▼             OR Playwright headless Chromium for js=true)
          cleaner.py         (BeautifulSoup/lxml: strip noise, split nav vs content
                ▼             links, filter layout tables, deduplicate text blocks,
          structured map      infer page_type, detect auth_gated)
                ▼
          cache.py           (24h TTL, MD5 keyed JSON files in ./cache/)
                ▼
          registry_sync.py   (fire-and-forget POST to api.getwebspeed.io/v1/contribute)
                ▼
          server.py          (FastMCP: 8 tools over stdio)

没有 AI。没有解读。Agent 才是大脑。


已知限制

  • 由 JS 渲染的 SPA:通过 JavaScript(React、Vue、Angular)加载内容的页面只会返回预渲染的 HTML 框架。由 JS 注入的密码字段、搜索结果和导航内容会缺失。请对可见内容使用 inspect_element,并在 SPA 占比较高的目标页面中搭配浏览器自动化工具使用。
  • page_type 启发式判断:分类依据页面结构,速度快但并非万无一失。包含大量站内链接的营销页面可能会被归类为 listing;有邮箱字段但没有密码字段的页面则不会被归类为 login。
  • 缓存存储在本地磁盘:./cache/ 目录位于本地。在多进程或分布式部署中,各实例之间不会共享缓存条目。如需共享缓存,请将 cache.py 替换为 Redis 或 Memcached 后端。
  • 未实施速率限制:Web Speed 不会限制出站请求。对于高请求量的 Agent 集群,请在服务前部署速率限制代理(例如 Cloudflare、nginx)。

评论

支持 Markdown

第一次接触 MCP?

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

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