Skip to main content
Glama

Web Speed

Web Speed решает проблему «сигнал-шум» для ИИ-агентов. В то время как современный веб оптимизирован для человеческого глаза (неряшливый HTML, сложные макеты, интерфейсы с тяжелым JS), Web Speed переводит этот хаос в детерминированную, эффективную с точки зрения токенов структурную карту, разработанную для высокопроизводительных агентских систем.

Никакого ИИ внутри. Никаких anthropic, openai или зависимостей от LLM любого рода. Вся интерпретация происходит на стороне вызывающего агента.


Зачем это нужно

Проблема

Решение Web Speed

«Сырой» HTML содержит более 150 000 символов скриптов, стилей и шума SVG

Удаляет все, что не является структурным → сокращение токенов до 97%

LLM галлюцинируют идентификаторы элементов и пропускают точки взаимодействия в «сыром» DOM

Возвращает замороженную структурную карту — что есть, то есть, ничего не выдумано

Пользовательские парсеры ломаются на каждом сайте

Детерминированный протокол — одинаковая структура JSON для любого сайта в сети

Агенту приходится переоткрывать страницы по одному запросу за раз

site_map сканирует весь домен за один вызов


Related MCP server: Delta-MCP

Инструменты

Инструмент

Описание

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. Шесть инструментов появятся в MCP-сервере web-speed.


Схемы вывода

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": "user@example.com",
    "password": "hunter2",
    "_csrf": "abc123"
  }
}

CSRF-токены помещаются в fields дословно — берите их из скрытых полей в массиве forms предыдущего вызова interpret_page. Создайте плоский словарь name → value и вызовите submit_form.


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"
}

Как агенту использовать вывод

Навигация по сайту: Читайте navigation для хрома сайта (меню, заголовок, подвал) и content_links для ссылок в теле страницы. content_links.total показывает, сколько их существует, даже если список обрезан. Выберите ссылку, соответствующую вашей цели, и вызовите interpret_page.

Отправка формы: Читайте forms. Каждое поле имеет name (что отправлять), type (какие данные ожидаются), label/placeholder (для чего это нужно), required и value. Скрытые поля (type: "hidden") содержат CSRF-токены — передавайте их value дословно. Создайте плоский словарь name → value и вызовите submit_form.

Классификация перед действием: Вызывайте page_type первым, когда нужно разветвить логику (например, это страница входа или панель управления?), не оплачивая полный вызов interpret_page.

Детализация компонента: Увидели таблицу на карте, но нужны отдельные строки? Список товаров, но нужны ссылка и цена каждой карточки? Вызовите inspect_element с CSS-селектором, чтобы получить структурированные детали по конкретным узлам без перезагрузки всей страницы.

Предварительное планирование многошагового процесса: Вызовите site_map перед началом. Вы получите заголовок, тип, глубину и исходящие ссылки каждой страницы, а также все формы на сайте — вы сможете спланировать весь рабочий процесс (найти форму входа, найти страницу ввода данных, найти конечную точку отправки) без единого лишнего запроса.

page_type — это сигнал, а не гарантия: Классификация является эвристической. SPA, отрисованные на JS, которые отдают пустые HTML-оболочки, часто будут классифицироваться как other — поле пароля не появится в HTML, пока не выполнится JavaScript. Используйте page_type как быстрый фильтр, а затем проверяйте фактические forms и headings.


Синхронизация общего реестра

По умолчанию каждая новая карта страницы, созданная вашим OSS-сервером, асинхронно передается в общий реестр Web Speed по адресу api.getwebspeed.io. Это краудсорсинговый маховик — каждый агент, который запрашивает URL, добавляет его в глобальный кэш, поэтому следующий агент в любом месте получает мгновенный ответ.

Это функция opt-out (отключение), а не opt-in (включение). Она включена по умолчанию, потому что чем больше участников, тем быстрее работают агенты у всех.

Что передается

Только структурные данные страницы:

  • Тип страницы, заголовок, описание

  • Заголовки, навигационные ссылки, ссылки на контент

  • Имена полей форм, типы и метки (без значений)

  • Таблицы, текстовые блоки

  • Метаданные Open Graph

Никогда не передаются: куки, токены сессии, значения форм, карты, отрисованные 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

Поведение синхронизации

  • Fire-and-forget: вклад отправляется в фоновом режиме. Запрос вашего агента завершается на полной скорости независимо от того, успешен ли пинг.

  • Только при промахе кэша (MISS): карты, которые уже есть в вашем локальном 24-часовом дисковом кэше, не отправляются повторно.

  • Ошибки молчаливы: сетевые ошибки, тайм-ауты и отказы сервера регистрируются только на уровне DEBUG и никогда не отображаются агенту.


Архитектура

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)

Никакого ИИ. Никакой интерпретации. Агент — это мозг.


Известные ограничения

  • JS-отрисованные SPA: Страницы, которые загружают контент через JavaScript (React, Vue, Angular), возвращают только предварительно отрисованную HTML-оболочку. Поля паролей, результаты поиска и навигация, внедряемые JS, будут отсутствовать. Используйте inspect_element на том, что видно, и сочетайте с инструментом автоматизации браузера для целей с тяжелыми SPA.

  • Эвристика page_type: Классификация структурная и быстрая, но не безошибочная. Маркетинговая страница с множеством внутренних ссылок может быть классифицирована как listing; страница с полем email, но без пароля, не будет login.

  • Кэш — это локальный диск: Директория ./cache/ локальна. В многопроцессорном или распределенном развертывании записи кэша не будут общими для всех экземпляров. Для общего кэширования замените cache.py на бэкенд Redis или Memcached.

  • Ограничения скорости не применяются: Web Speed не ограничивает исходящие запросы. Для высоконагруженных агентских систем установите прокси-сервер с ограничением скорости (например, Cloudflare, nginx) перед сервером.

Related MCP Connectors

Related MCP Servers