Skip to main content
Glama

web-ui-tester

MCP-сервер, который позволяет ИИ быстро управлять реальными веб-страницами и исследовать их в браузерных сессиях, которые остаются активными между вызовами инструментов.

Быстроту обеспечивают две вещи. Страницы представляются в виде дерева доступности со ссылками на элементы, а не скриншотов или сырого HTML, поэтому модель может находить элементы и кликать их, не тратя контекст на разметку и не дожидаясь анализа изображений. А сессии сохраняются — cookies, состояние страницы и история переживают вызовы, так что длинное взаимодействие — это серия дешёвых шагов, а не повторные холодные старты.

Кроме того, он умеет диагностику уровня DevTools — консоль, сеть с телами ответов, выполнение JS, вычисленные стили, — чтобы ИИ мог разобраться, почему что-то сломано, а не просто констатировать поломку.

Быстрый старт

claude mcp add web-ui-tester -- npx -y web-ui-tester

С ключом для встроенного агента (см. run_task):

claude mcp add web-ui-tester \
  -e GOOGLE_GENERATIVE_AI_API_KEY=your-key \
  -- npx -y web-ui-tester

Или в конфигурационном файле любого MCP-клиента:

{
  "mcpServers": {
    "web-ui-tester": {
      "command": "npx",
      "args": ["-y", "web-ui-tester"],
      "env": { "GOOGLE_GENERATIVE_AI_API_KEY": "your-key" }
    }
  }
}

Chromium поставляется через Playwright. Если он ещё не установлен:

npx playwright install chromium

Как работают сессии

browser_start          → sessionId, kept alive across calls
browser_navigate       → page state + snapshot with [ref=eN] handles
browser_click ref=e12  → act on what the snapshot showed you
browser_snapshot       → fresh refs after the page changes
browser_close          → done (or let it idle out after 30 minutes)

Всё после browser_start использует этот sessionId. Снимок — главное, к чему стоит привыкнуть:

- generic [ref=e1]:
  - heading "Signup" [level=1] [ref=e2]
  - textbox "Name" [ref=e5]:
    - /placeholder: Your name
  - combobox "Plan" [ref=e7]
  - button "Create account" [ref=e10]
  - link "Go to second page" [ref=e12] [cursor=pointer]:
    - /url: /second.html

Эти ссылки напрямую уходят в browser_click, browser_type и остальные инструменты. Они привязаны к состоянию страницы, которое их создало: после навигации или изменения DOM сделайте новый снимок снова. Когда инструмент сообщает, что ссылка больше недействительна, делайте новый снимок, а не повторяйте попытку — об этом явно сказано в сообщении. Инструменты адресации элементов также принимают css или role + name, если вы уже знаете селектор и предпочитаете пропустить снимок.

Инструменты

Сессияbrowser_start (параметры: userAgent, viewportWidth, viewportHeight, headless, baseUrl, url, model), browser_list, browser_close.

Взаимодействиеbrowser_navigate, browser_click, browser_type, browser_press_key, browser_hover, browser_select_option, browser_scroll, browser_wait_for, browser_go_back, browser_handle_dialog.

Действия сообщают, к чему привели: навигация, новые ошибки консоли, количество запросов и любой появившийся диалог возвращаются в результатах. Поэтому клик, который тихо что-то сломал, не выглядит как успех.

Про диалоги нужно пояснить отдельно. alert/confirm/prompt блокирует страницу, пока не получит ответ, поэтому действие, которое его открыло, не может одновременно на него ответить — неотвеченный диалог закрывается автоматически, не подвешивая клик, и в результате это будет сообщено. Чтобы принять такой диалог или заполнить поле prompt, вызовите browser_handle_dialog до действия, которое его запускает, — и ответ будет готов повешен для следующего диалога.

Инспекцияbrowser_snapshot (можно ограничить областью по элементу, с лимитом по depth, interactiveOnly, постранично через offset), browser_query (поиск по роли/имени, тексту или CSS — возвращает ссылки и состояние), browser_read_text (отрисованный текст страницы или одного поддерева), browser_screenshot (доступен, но дерево обычно всё равно удобнее).

Диагностикаbrowser_console (сообщения плюс необработанные перехваченные ошибки со стеками), browser_network (статусы, размеры, тайминги), browser_request_detail (заголовки, тайминг-разбивка, запрос и тела ответов), browser_evaluate (выполнение JS на странице), browser_inspect_element (вычисленные стили, блочная модель, состояние формы).

Каждый результат ограничен по символам, а крупные (browser_snapshot, browser_read_text, тела) разбиваются на страницы с offset, а не молча обрезаются.

Встроенный агент

run_task передаёт сессию быстрой модели, которая сама управляет браузером и возвращает отчёт:

run_task(sessionId, "Log in as demo@example.com / hunter2 and check the
                     dashboard loads without errors")

Смысл — в отчётности. Возвращается структурированный вердикт, а не просто текст:

status: success
model: google:gemini-flash-lite-latest

Logged in and opened the dashboard. The revenue widget rendered empty.

findings (3):
  [error] Request failed: GET 500 [observed by the harness]
      where: https://app.example.com/api/revenue
      evidence: HTTP 500
  [error] Console exception on the page [observed by the harness]
      where: app.js:214:9
      evidence: TypeError: Cannot read properties of undefined (reading 'total')
  [warning] The revenue widget shows no empty state, just blank space
      where: #revenue-card
      evidence: card is present but contains no text

Находки приходят из двух источников, и различие важно. Агент вызывает report_finding по ходу работы — поэтому прогон, упёршийся в лимит шагов, всё равно вернёт всё, что удалось найти к этому моменту. Затему обвязка записывает каждый показываемый в сессии console, каждый упавший запрос и каждый диалог и сообщает о них вне зависимости от того, упомянул ли их агент, с пометкой [observed by the oks]. Модель, которая пропустила 500-ю или забыла упомянуть исключение, не сможет этого скрыть.

Тот же отчёт возвращается как structuredContent по объявленной схеме вывода, поэтому вызывающий ИИ может разойти по findings[].severity, а не разбирать текст. Задача может быть успешной и содержать находки; success отражает, выполнена ли задача, а не то, была ли страница чистой.

Это единственная часть, требующая API-ключ. По умолчанию используется Gemini Flash Lite ради низкой задержки; Anthropic тоже подходит:

Модель по умолчанию

Ключ

Google

gemini-flash-lite-latest

GOOGLE_GENERATIVE_AI_API_KEY

Anthropic

claude-haiku-4-5

ANTHROPIC_API_KEY

Настройте WUT_MODEL, чтобы выбрать (anthropic, или google:gemine-flash-latest, или любой provider:modelId). Сессия может переопределить это через model в browser_start, а отдельный разговор — через model в run_task. Все остальные инструменты работают без ключа.

HTTP-режим

web-ui-tester --port 7399
claude mcp add --transport http web-ui-tester http://127.0.0.1:7399/mcp

В этом режиме сессии браузера живут в долго работающем сервере, а не в процессе-клиенте, поэтому они переживают перезапуски клиента и переподключения — снова подключитесь, передайте тот же sessionId, и страница всё ещё на месте. GET /health возвращает количество сессий и подключений.

По умолчанию он привязывается к 127.0.0.1, где действует защита от DNS-ребindingа. --host расширяет этот диапазон, и сервер предупреждает об этом: аутентификации не предусмотрено, и любой, кто может обратиться к серверу, может запустить браузер и выполнять через него JavaScript. Поместите его за прокси или файрволом.

Конфигурация

Переменная

По умолчанию

Назначение

WUT_MODEL

google:gemini-flash-lite-latest

Модель для run_task, в формате provider[:modelId]

GOOGLE_GENERATIVE_AI_API_KEY

Ключ для Gemini

ANTHROPIC_API_KEY

Ключ для Anthropic

WUT_USER_AGENT

AITester/1.0

User-Agent по умолчанию для новых сессий

WUT_HEADLESS

true

Фоновый режим по умолчанию (headless)

WUT_IDLE_TIMEOUT_MS

1800000

Закрывать сессии, бездействующие так долго

WUT_MAX_OUTPUT_CHARS

15000

Лимит символов на результат инструмента

WUT_ACTION_TIMEOUT_MS

5000

Таймаут на одно действие с элементом

WUT_AGENT_MAX_STEPS

20

Бюджет шагов по умолчанию для run_task

WUT_EXECUTABLE_PATH

Явный исполняемый файл Chromium

PLAYWRIGHT_BROWSERS_PATH

Где Playwright ищет браузеры

Флаги командной строки: --port, --host, --headless / --no-headless, --idle-timeout, --version, --help.

Если нужная Playwright ревизия Chromium не установлена, но есть другая, сервер найдёт и использует её, а не завершится ошибкой — удобно в предварительно собранных контейнерах. WUT_EXECUTABLE_PATH полностью переопределяет этот поиск.

Разработка

npm install
npm run build
npm test          # agent loop (mocked model) + full end-to-end suite
npm run typecheck

npm test прогоняет цикл агента на сценарной мок-модели, затем ведёт собранный сервер настоящим MCP-клиентом из обеих транспортов против локального приложения-фикстуры — покрывая ссылки (refs), обработку устаревших ссылок, диагностику, сохранение сессий при переподключениях и вычистку бездействующих сессий. npm run test:agent:live дополнительно прогоняет run_task против реального провайдера и автоматически пропускается, если ключ не задан.

Лицензия

MIT

-
license - not tested
Not graded
quality - not tested
C
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 Connectors

  • Reliable web access for AI agents: smart HTTP, rotating proxies, and full-browser rendering.

  • Live browser debugging for AI assistants — DOM, console, network via MCP.

  • Browser-backed QA with evidence and fix-ready reports for coding agents.

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/hofmeister/web-ui-tester'

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