Настройка 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 вкладываетLaunchOptionsPlaywright внутрь объектаbrowser, а неизвестный ключ верхнего уровня игнорируется, а не отклоняется. - Существуют два других маршрута, и ошибиться в них проще: флаг командной строки
--executable-pathи переменная окруженияPLAYWRIGHT_MCP_EXECUTABLE_PATH. Для одного развёртывания выбирается один маршрут, чтобы устаревшее значение не получило приоритет. - Флаг профиля размещается в
launchOptions.argsотдельным элементом массива, потому что Playwright передаёт каждый элемент как самостоятельный аргумент. - Бинарный файл подтверждается изнутри сессии: читаются
navigator.userAgent, путь процесса, который сообщает сервер, и маркер уровня страницы, который предоставляет собственная сборка. Сервер, откатившийся к встроенному Chromium, отвечает иначе по всем трём признакам. - На один профиль приходится один экземпляр MCP-сервера. Постоянный профиль блокируется одним экземпляром браузера, поэтому два клиента с общим рабочим каталогом конфликтуют вместо изоляции.
Содержание
- Где размещается путь к исполняемому файлу
- Передача профиля без потери аргумента
- Проверка того, какой бинарный файл запущен
- Режимы отказа и ветка резервного запуска
- Практический вывод
Где размещается путь к исполняемому файлу
Файл конфигурации 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
Эта статья входит в руководство: Развёртывание и выпуск браузера: операционная карта
Похожие статьи
Настройка MCP-сервера Puppeteer для собственной сборки
Начало работыБезголовый браузер для ИИ-агентов: запуск и границы инструментов
РазвертываниеАвтоматизация браузера со Stagehand
Начало работыНастройка browser-use с управляемым браузером
Начало работыPlaywright и согласованные профили идентичности браузера
Начало работыНачало работы с автоматизацией браузера: карта
Выполните ту же проверку в BotBrowser
Загрузите профиль, сохраните внутри браузера те сигналы, о которых только что прочитали, и подтвердите результат на своей машине до раскатки.