Назад в Центр знаний
Развертывание

Настройка Playwright MCP для собственной сборки Chromium

Настройка сервера Playwright MCP для запуска выбранной сборки Chromium с профилем и проверка внутри сессии того, какой файл стартовал.

BotBrowser Team

Документация

Нужна структурированная документация по теме Развертывание?

Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.

Сервер Playwright MCP располагается между клиентом агента и браузером, а браузер, который он запускает, определяется конфигурацией, которую легко оставить без проверки. При корректной конфигурации агент управляет той сборкой и тем профилем, которые выбрал оператор. При ошибке сервер запускает собственный встроенный Chromium и сообщает об успехе, поэтому агент может выполнить всю задачу в браузере, который никто не планировал использовать. Ключи конфигурации, передающие собственный исполняемый файл, обратное чтение, доказывающее, какой бинарный файл стартовал, и режим отказа, в котором аргумент профиля молча отбрасывается, определяют, запустит ли сервер нужную сборку. Playwright MCP это проект Microsoft с отдельным циклом выпусков, и приведённая конфигурация соответствует опубликованной схеме. BotBrowser поддерживает executablePath и аргумент профиля от любого совместимого с Playwright средства запуска, и не предоставляет собственный MCP-сервер, поэтому не может исправить сервер, который не передаёт параметр дальше.

TL;DR

  • Исполняемый файл указывается в browser.launchOptions.executablePath, а не в ключе верхнего уровня. Схема конфигурации MCP вкладывает LaunchOptions Playwright внутрь объекта browser, а неизвестный ключ верхнего уровня игнорируется, а не отклоняется.
  • Существуют два других маршрута, и ошибиться в них проще: флаг командной строки --executable-path и переменная окружения PLAYWRIGHT_MCP_EXECUTABLE_PATH. Для одного развёртывания выбирается один маршрут, чтобы устаревшее значение не получило приоритет.
  • Флаг профиля размещается в launchOptions.args отдельным элементом массива, потому что Playwright передаёт каждый элемент как самостоятельный аргумент.
  • Бинарный файл подтверждается изнутри сессии: читаются navigator.userAgent, путь процесса, который сообщает сервер, и маркер уровня страницы, который предоставляет собственная сборка. Сервер, откатившийся к встроенному Chromium, отвечает иначе по всем трём признакам.
  • На один профиль приходится один экземпляр MCP-сервера. Постоянный профиль блокируется одним экземпляром браузера, поэтому два клиента с общим рабочим каталогом конфликтуют вместо изоляции.

Схема конфигурации от клиента агента через сервер MCP к разрешённому пути исполняемого файла, с отдельной ветвью молчаливого отката, где сервер запускает собственный встроенный Chromium, если executablePath не передан.

Содержание

Где размещается путь к исполняемому файлу

Файл конфигурации MCP представляет собой JSON-документ с объектом browser. Внутри этого объекта launchOptions имеет тип LaunchOptions Playwright, тот же самый тип, который прямой скрипт Playwright передаёт в browserType.launch. Именно там находится executablePath, и только это вложение читает сервер.

{
  "browser": {
    "browserName": "chromium",
    "launchOptions": {
      "executablePath": "/opt/botbrowser/chrome",
      "headless": true,
      "args": ["--bot-profile=/etc/botbrowser/profile.enc"]
    },
    "contextOptions": {
      "viewport": { "width": 1280, "height": 800 }
    }
  }
}

Три свойства этого блока важнее остальных. browserName остаётся chromium, потому что собственная сборка Chromium по-прежнему говорит по протоколу Chromium, а значения firefox и webkit направили бы запуск к другому драйверу. headless размещается в launchOptions, а не рядом с browserName, поскольку сервер передаёт весь объект в вызов запуска. args представляет собой массив отдельных строк, и каждый элемент становится одним аргументом; единая строка с пробелом внутри не разделяется.

МаршрутКуда помещается значениеЧто перекрываетТипичная ошибка
Файл конфигурацииbrowser.launchOptions.executablePathНичего, если не задан также флаг или переменная окруженияЗапись executablePath на верхнем уровне файла
Флаг командной строки--executable-path /path/to/chromeФайл конфигурацииПредположение, что флаг задаёт ещё и browserName
Переменная окруженияPLAYWRIGHT_MCP_EXECUTABLE_PATH=/path/to/chromeФайл конфигурацииУстаревшее значение, унаследованное из профиля оболочки

Три маршрута являются альтернативами, а не слоями. Развёртывание, которое задаёт файл конфигурации и одновременно экспортирует переменную окружения, получает два источника истины, и браузер определяется тем, который сервер прочитает последним. Выбирается один маршрут, а для остальных в среде запуска проверяется отсутствие значения.

Почему неизвестный ключ не вызывает ошибки

Сервер проверяет ту структуру, которую знает, и игнорирует всё, что не распознаёт. Конфигурация, помещающая executablePath на верхний уровень, пишущая executable_path или вкладывающая ключ в contextOptions вместо launchOptions, даёт сервер, который стартует нормально, и браузер, который не является нужным. Журнал запуска не обязательно сообщает об этом, потому что с точки зрения сервера конфигурация была допустимой, а запуск завершился успешно.

Именно поэтому обратное чтение из следующего раздела не является необязательным. Трактовка успешного старта как доказательства нужного бинарного файла представляет собой способ провалить такую настройку, который легче всего упустить, причём провал идёт в самую опасную сторону: агент работает, задача завершается, а браузер оказывается не тем.

Параметры контекста отделены от параметров запуска

contextOptions представляет собой другой объект и несёт BrowserContextOptions, а не LaunchOptions. Размер области просмотра, локаль, часовой пояс, цветовая схема и разрешения принадлежат этому объекту. Перенос executablePath в contextOptions создаёт недопустимый параметр контекста, который игнорируется, и браузер откатывается к встроенной сборке.

Разделение стоит помнить, потому что в плоском JSON-файле два объекта выглядят взаимозаменяемыми. Полезная привычка: прочитать файл перед запуском и проверить, что browser.launchOptions.executablePath является строкой, указывающей на существующий исполняемый файл на диске, а browser.contextOptions не содержит значений, похожих на путь.

Приоритет между тремя маршрутами

Когда путь задают несколько маршрутов, результат зависит от того, какой сервер прочитает последним, и этот порядок не подлежит угадыванию. Безопасный шаблон делает два других маршрута невозможными: переменная PLAYWRIGHT_MCP_EXECUTABLE_PATH снимается в среде запуска сервера, а флаг --executable-path не передаётся в командной строке, если файл конфигурации уже содержит значение.

Конкретная проверка занимает одну команду в среде запуска: вывести переменную и подтвердить, что она пуста, затем стартовать сервер. Профиль оболочки, который экспортирует переменную для постороннего проекта, часто становится причиной запуска встроенного браузера при правильном файле конфигурации, потому что переопределения из окружения объединяются после чтения файла конфигурации, поэтому унаследованное значение получает приоритет.

Те же рассуждения относятся к скрипту-обёртке, собирающему командную строку. Если обёртка добавляет --executable-path из переменной, пустой в одной из сред, флаг может исчезнуть целиком, и файл конфигурации останется единственным источником. Это желаемый результат, поэтому обёртку пишут так, чтобы флаг опускался, а не передавался пустым.

Передача профиля без потери аргумента

Профиль не является параметром запуска, известным Playwright. Это аргумент браузера, поэтому он передаётся в launchOptions.args отдельным элементом массива. Прямой скрипт Playwright записывает его таким же образом, и именно профиль чаще всего теряется при преобразовании рабочего скрипта в конфигурацию MCP.

{
  "browser": {
    "browserName": "chromium",
    "launchOptions": {
      "executablePath": "/opt/botbrowser/chrome",
      "args": ["--bot-profile=/etc/botbrowser/profile.enc", "--bot-locale=en-US"]
    }
  }
}

Каждый аргумент представляет собой один элемент массива без окружающих кавычек оболочки. "--bot-profile=/etc/botbrowser/profile.enc" и "--bot-profile=/etc/botbrowser/profile.enc --bot-locale=en-US" не эквивалентны: вторая строка является одним аргументом с пробелом внутри, и браузер получает один искажённый флаг вместо двух.

Откуда читается профиль

Файл профиля должен быть доступен для чтения процессу, который порождает сервер, а это не всегда тот процесс, который запустил оператор. Сервер, запущенный настольным клиентом, наследует окружение этого клиента, а сервер внутри контейнера видит только смонтированные данные. Поэтому путь, работающий в интерактивной оболочке, может не сработать при запуске через MCP, и отказ проявится как браузер со значениями по умолчанию, а не как ошибка.

Абсолютный путь определяется один раз, в той же среде, которая запускает сервер, и записывается рядом с конфигурацией. Относительные пути разрешаются относительно рабочего каталога сервера, который выбирает клиент и который оператор редко задаёт осознанно.

Один экземпляр сервера, один профиль

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

ЗадачаНастройкаПоследствие
Один клиент, один фиксированный профильПостоянный профиль и один экземпляр сервераПрофиль заблокирован этим экземпляром
Несколько клиентов параллельноРежим изоляции или отдельный каталог пользовательских данных для каждого клиентаОбщее состояние отсутствует; профиль не переживает перезапуск
Повторное использование уже запущенного браузераПодключение к существующей конечной точкеСервер вообще не запускает настроенный исполняемый файл

Третья строка содержит ловушку для развёртывания собственной сборки. Подключение к существующей конечной точке полностью обходит путь запуска, поэтому executablePath из конфигурации не читается. Команда, добавившая конечную точку CDP для ускорения старта, может молча потерять собственную сборку, не изменив ни одного параметра запуска.

Состояние профиля и потери при перезапуске

Разница между постоянным и изолированным профилем заключается не только в хранении. Постоянный профиль несёт файлы cookie, локальное хранилище и кэшированное состояние, по которому сайт узнаёт вернувшегося посетителя. Изолированный профиль начинает чисто при каждом закрытии браузера, поэтому задача, зависящая от авторизованной сессии, должна явно внедрять это состояние, а не рассчитывать на его сохранение.

Для мониторинга или тестирования такой компромисс подходит, потому что чистый старт делает два прогона сопоставимыми. Для задачи, которая обязана оставаться авторизованной, нужен постоянный профиль, и ограничение в один экземпляр становится рабочим условием, а не помехой. Запись режима, использованного в прогоне, рядом с путём профиля не позволяет позже принять различие между изолированным и постоянным прогоном за различие в поведении.

Проверка того, какой бинарный файл запущен

Единственная надёжная проверка выполняется внутри сессии, которой управляет агент. Три измерения вместе отличают нужную сборку от встроенного резервного варианта, и каждое из них недорого.

Первое измерение это строка пользовательского агента. Собственная сборка может сообщать другую версию Chromium, чем встроенная, а может сообщать настроенный user agent, не соответствующий ни одной сборке, поэтому это чтение подтверждает, но не решает. Встроенный Chromium Playwright сообщает версию, поставленную с установленным пакетом Playwright. Эти значения различаются, и разница видна при одном чтении navigator.userAgent.

Второе измерение это путь исполняемого файла, который сообщает процесс. Там, где сборка его предоставляет, значение читается со страницы; там, где не предоставляет, оно читается из списка процессов сервера на хосте, который его породил. В любом случае значение должно совпадать с путём в конфигурации посимвольно.

Третье измерение это маркер, который устанавливает собственная сборка и не устанавливает стандартная. Это может быть дополнительное свойство объекта браузерного API, строка версии в пространстве имён продукта или документированный флаг возможности. Маркер сильнее двух других признаков, потому что случайно совпавший номер версии его не создаёт.

ИзмерениеОтвет нужной сборкиОтвет встроенного резервного вариантаГде читается
navigator.userAgentВерсия Chromium собственной сборкиВерсия, встроенная в PlaywrightЛюбая страница сессии
Путь исполняемого файла процессаНастроенный путьПуть внутри кэша PlaywrightСписок процессов сервера или чтение со страницы, где оно доступно
Маркер собственной сборкиПрисутствуетОтсутствует или имеет значение по умолчаниюСкрипт страницы, читающий конкретное свойство

Обратное чтение, проверяющее только первое измерение, слабое, потому что собственная сборка может делить строку версии со встроенной. Чтение, проверяющее только третье измерение, тоже слабое, потому что оно доказывает возможность, а не идентичность процесса, обслуживающего страницу. Проверяются путь и маркер, а пользовательский агент служит подтверждением.

Обратное чтение, выполняемое агентом

Проверке не нужен отдельный стенд. Клиент вычисляет короткое выражение в сессии и возвращает результат; агент сравнивает его с настроенным путём, не покидая диалог. Значение имеет явное и записанное сравнение, а не автоматизация сама по себе.

На каждую сессию записываются три значения: настроенный путь, наблюдаемый путь и результат проверки маркера. Сессия с совпадающим путём и присутствующим маркером соответствует нужной сборке. Сессия с несовпадающим путём относится к резервному варианту независимо от того, что сообщает пользовательский агент.

Чтение пути, когда сборка его не предоставляет

Не каждая сборка открывает собственный путь исполняемого файла скрипту страницы, и отсутствие такого доступа не является дефектом. Там, где страница не может ответить, читается список процессов на хосте, который породил сервер, и сопоставляется дочерний процесс сервера. Родственное отношение и есть предмет проверки: на машине может работать несколько процессов Chromium, и значение имеет потомок MCP-сервера, а не браузер, открытый вручную.

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

Режимы отказа и ветка резервного запуска

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

СимптомПричинаПодтверждениеИсправление
Браузер стартует, версия в пользовательском агенте невернаяexecutablePath не прочитанКлюч находится на верхнем уровне файла или внутри contextOptionsПеренести его в browser.launchOptions
Браузер стартует, настройки профиля отсутствуютФлаг профиля отброшен или искажёнargs содержит одну строку с пробелом вместо отдельных элементовРазделить на один элемент массива на каждый флаг
Сервер завершается с ошибкой запускаНастроенный путь отсутствует или не является исполняемымПуть не разрешается в среде сервераИспользовать абсолютный путь, доступный порождающему процессу
Второй клиент не может запустить браузерПостоянный профиль уже заблокированОба клиента указывают на один каталог пользовательских данныхВключить изоляцию или выделить каждому клиенту отдельный каталог
Собственная сборка игнорируется после ускорения стартаНастроена существующая конечная точкаКонфигурация по-прежнему содержит конечную точкуУдалить конечную точку, чтобы выполнялся путь запуска

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

Что клиент видит и чего не видит

Клиент MCP видит инструменты, которые предоставляет сервер: навигацию, снимок состояния, щелчок, ввод текста и всё остальное, что публикует сервер. Он не видит конфигурацию запуска, порождённый процесс и переданные аргументы. Именно из-за этой асимметрии обратное чтение запрашивается через сессию, а не предполагается со стороны клиента.

Это же объясняет, почему клиент не может обнаружить откат самостоятельно. Распределение ответственности между циклом агента и процессом браузера разобрано в статье headless-браузер для ИИ-агентов, прямой скрипт, который должна воспроизвести эта конфигурация, есть в руководстве по началу работы с Playwright, а плоская форма объекта запуска, которую ожидает сервер на Puppeteer, разобрана в статье настройка MCP-сервера Puppeteer. С точки зрения клиента сервер работает правильно, и это действительно так: сервер запустил браузер и обслуживает инструменты против него. Единственная сторона, знающая, какой браузер был задуман, это оператор, написавший конфигурацию.

Запись результата проверки

Проверка, которая не записана, будет повторена. Настроенный путь, наблюдаемый путь, результат маркера и отметка времени хранятся вместе, чтобы следующая сессия могла сравнить значения, не выводя заново, что означало «правильно» в тот момент. При изменении конфигурации сохранённая запись делает изменение видимым, а не молчаливым.

Та же дисциплина нужна прямому запуску Playwright, а под сервером MCP она важнее потому, что запуск находится на один слой дальше от человека, написавшего параметры. Клиент этот слой не видит, поэтому запись остаётся единственным долговременным доказательством того, что слой настроен как задумано.

FAQ

Читает ли Playwright MCP executablePath на верхнем уровне файла конфигурации?

Нет. Схема вкладывает LaunchOptions Playwright в browser.launchOptions, и ключ верхнего уровня не является частью этой структуры. Сервер игнорирует то, что не распознаёт, поэтому ключ в неверном месте даёт обычный старт со встроенным браузером вместо ошибки проверки.

Может ли один сервер MCP обслуживать несколько профилей одновременно?

Не через один постоянный профиль. Постоянный профиль заблокирован одним экземпляром браузера, поэтому параллельным клиентам нужен режим изоляции или отдельные каталоги пользовательских данных. Режим изоляции держит профиль в памяти и отбрасывает его при закрытии, что является другим компромиссом, а не способом разделить один профиль.

Достаточно ли совпадающего пользовательского агента, чтобы доказать запуск нужной сборки?

Нет. Собственная сборка может сообщать ту же версию Chromium, что и встроенная, поэтому совпадение версии служит подтверждением, а не доказательством. Сравнивается путь исполняемого файла процесса с настроенным путём и читается маркер, который предоставляет только собственная сборка.

Практический вывод

Исполняемый файл записывается в browser.launchOptions.executablePath, каждый флаг профиля и локали размещается в собственном элементе args, а из трёх маршрутов задания пути выбирается ровно один. Затем агент читает путь процесса и маркер конкретной сборки до начала реальной работы.

Следующее действие занимает одну сессию: запустить сервер с конфигурацией, попросить клиента вернуть navigator.userAgent и наблюдаемый путь исполняемого файла, сравнить оба значения с файлом. При совпадении пути настройка доказана. При несовпадении сервер работает со встроенным Chromium, и каждый результат этой сессии описывает браузер, который не был выбран. Две смежные темы несут ту же проблему проверки: настройка безголового браузера для ИИ-агентов описывает передачу браузера агенту, а руководство по началу работы с Playwright описывает прямой скрипт, который конфигурация MCP должна воспроизвести.

Sources

#Playwright MCP#MCP-Сервер#executablePath#Автоматизация Браузера#ИИ-Агент

Эта статья входит в руководство: Развёртывание и выпуск браузера: операционная карта

Выполните ту же проверку в BotBrowser

Загрузите профиль, сохраните внутри браузера те сигналы, о которых только что прочитали, и подтвердите результат на своей машине до раскатки.