Настройка MCP-сервера Puppeteer для собственной сборки
Настройка MCP-сервера Puppeteer для запуска выбранной сборки Chromium с профилем: executablePath, args, headless и проверка процесса.
BotBrowser Team
Нужна структурированная документация по теме Развертывание?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
MCP-сервер Puppeteer управляет запуском браузера, поэтому переданная ему конфигурация определяет, какой двоичный файл Chromium и какой профиль получает каждая задача агента. LaunchOptions в Puppeteer имеет другую структуру, чем у Playwright, а конфигурация, перенесённая между ними, молча теряет части, которых нет на другой стороне. Отказ происходит без сообщения: сервер стартует, инструменты отвечают, а браузер оказывается тем, который сервер использовал бы и без настройки. Документация Puppeteer описывает executablePath как путь, применяемый вместо встроенного браузера, и предупреждает, что поддержка гарантируется только для собственной сборки, поэтому параметр требует осознанного выбора, а не прозрачной подстановки. BotBrowser поддерживает запуск из Puppeteer через executablePath и аргумент профиля в args, но не может предоставить собственный MCP-сервер, поэтому сервер, не передающий эти значения дальше, нельзя исправить со стороны браузера.
TL;DR
- Объект запуска Puppeteer размещает
executablePath,args,headless,userDataDir,ignoreDefaultArgs,pipeиbrowserна одном уровне. Playwright вкладывает те же идеи вlaunchOptions, поэтому две структуры не взаимозаменяемы. headlessв Puppeteer принимаетtrue,falseили строку'shell', причём'shell'выбирает старую реализацию headless. Логическое значение в стиле Playwright здесь допустимо, а целиком скопированная конфигурация Playwright нет.executablePathзаменяет встроенный браузер, и документация Puppeteer предупреждает, что гарантия дана только для встроенной сборки. Пользовательский путь считается поддерживаемой, но неподтверждённой конфигурацией, а доказательство даёт обратное чтение процесса.- Профиль передаётся в
argsотдельным элементом, как и в Playwright, поскольку это аргумент браузера, а не параметр Puppeteer. ignoreDefaultArgsиpipeменяют то, что сервер передаёт процессу. Сервер сignoreDefaultArgs: trueотбрасывает флаги, добавляемые Puppeteer, поэтому итоговый argv не совпадает ни с заданным, ни со стандартным набором Puppeteer.
Содержание
- Где находится объект запуска Puppeteer
- Чем он отличается от структуры Playwright MCP
- Передача профиля и режима headless
- Проверка фактически запущенного двоичного файла
- Практический вывод
Где находится объект запуска Puppeteer
LaunchOptions в Puppeteer представляет собой один плоский объект, передаваемый в puppeteer.launch(). executablePath входит в него на верхнем уровне наряду с args, headless, userDataDir, ignoreDefaultArgs, pipe, browser, channel и debuggingPort. Обёртки launchOptions нет, поскольку весь объект и есть параметры запуска.
{
"mcpServers": {
"puppeteer": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-puppeteer"],
"env": {
"PUPPETEER_EXECUTABLE_PATH": "/opt/botbrowser/chrome",
"PUPPETEER_LAUNCH_OPTIONS": "{\"headless\":true,\"args\":[\"--bot-profile=/etc/botbrowser/profile.enc\"]}"
}
}
}
}
Пример выше показывает два способа, которыми сервер может получать значения: отдельную переменную окружения для исполняемого файла и JSON-блок для остального. Ни одно из имён не стандартизировано среди серверов на базе Puppeteer, поэтому первая проверка состоит в чтении документации самого сервера: там указана точная переменная или флаг, а затем подтверждается прибытие значения.
| Элемент Puppeteer | Тип | Влияние на собственную сборку |
|---|---|---|
executablePath | string | Заменяет встроенный браузер; Puppeteer гарантирует поддержку только собственной сборки |
args | string[] | Дополнительные аргументы командной строки, по одному элементу массива на аргумент |
headless | boolean или 'shell' | true включает новый режим headless, 'shell' включает старый |
userDataDir | string | Постоянный каталог профиля, отдельный от аргумента профиля BotBrowser |
ignoreDefaultArgs | boolean или string[] | Удаляет стандартные флаги Puppeteer или отфильтровывает названные |
pipe | boolean | Передаёт протокол через stdio вместо WebSocket |
browser | SupportedBrowser | Выбирает семейство браузера, которое ожидает Puppeteer |
channel | ChromeReleaseChannel | Ищет установленный Chrome в известном расположении вместо встроенного файла |
Две строки таблицы заслуживают внимания при развёртывании собственной сборки. channel и executablePath оба могут указывать на браузер, а документация Puppeteer описывает channel как поиск обычной установки Chrome в известном системном расположении. Одновременная установка оставляет два ответа на один вопрос, и побеждающий из них относится к деталям реализации, которые лучше исключить, чем проверять.
Почему плоскую структуру легко прочитать неверно
Плоский объект не даёт структурного сигнала о том, какие ключи относятся к запуску, а какие принадлежат контексту. В Playwright ключ, размещённый неверно, попадает в другой объект и игнорируется; в Puppeteer ключ, отсутствующий в LaunchOptions, просто не входит в параметры, и у puppeteer.launch() нет причины жаловаться. Результат тот же, но другим маршрутом: сервер стартует, а один из параметров так и не применяется.
Практическая проверка состоит в выписывании объекта и сравнении его ключей с документированными элементами LaunchOptions. Всё, чего нет в этом списке, не является параметром запуска, независимо от внешнего вида.
Что Puppeteer делает с непригодным путём
executablePath указывает на файл, и Puppeteer запускает этот файл. Если путь не существует, не разрешается в рабочем каталоге сервера или существует, но недоступен для исполнения учётной записью сервера, программа запуска выдаёт ошибку вместо подстановки другого двоичного файла; это следует из того, что Puppeteer передаёт указанный путь порождаемому процессу, и это вывод о поведении программы запуска, а не фраза со страницы LaunchOptions. Такое поведение противоположно молчаливому случаю: неверный путь, который существует, даёт работающий браузер, но не тот, который задуман, а несуществующий путь даёт ошибку, видимую оператору.
Скрытый отказ возникает там, где путь действителен и ведёт в другое место. Сервер, подставляющий стандартный путь при отсутствии конфигурации, создаёт именно такую картину: действительный исполняемый файл, работающий браузер и отсутствие ошибки. Проверка сравнивает наблюдаемый путь с намеченным, а не факт существования пути.
Что сервер добавляет сверху
MCP-сервер на базе Puppeteer является обёрткой: он читает собственную конфигурацию, строит объект LaunchOptions и вызывает puppeteer.launch(). Всё, что сервер добавляет между своей конфигурацией и этим вызовом, снаружи невидимо. Поэтому обратное чтение здесь важнее, чем в прямом скрипте, где объект параметров написан оператором.
Вариант этой обёртки для Playwright, с его вложенной формой и незаметным откатом к встроенному браузеру, разобран в статье настройка Playwright MCP для собственной сборки Chromium, а распределение ответственности между циклом агента и процессом браузера есть в статье headless-браузер для ИИ-агентов. Сервер может добавить стандартный массив args, значение headless по умолчанию или ignoreDefaultArgs. Сервер, дописывающий собственные аргументы, создаёт argv как объединение заданных значений и своих стандартных, в порядке, который оператор не выбирал. Чтение работающего процесса остаётся единственным способом увидеть это объединение.
Почему итоговый argv важнее конфигурации
Два запуска могут использовать один файл конфигурации и всё равно стартовать разные браузеры, если версия сервера изменила стандартные значения между ними. Сервер, который начинает добавлять новый флаг по умолчанию или перестаёт добавлять прежний, меняет итоговый argv, не касаясь файла оператора. Браузер читает argv, а не конфигурацию сервера, поэтому наблюдаемое поведение следует за argv.
Отсюда правило записывать итоговый argv рядом с наблюдением, а не только конфигурацию, которая его создала. Конфигурация вместе с версией сервера воспроизводима; одна конфигурация перестаёт быть воспроизводимой, как только сервер меняет добавляемые значения.
Чем он отличается от структуры Playwright MCP
Две экосистемы отвечают на один вопрос разными структурами, и именно эти различия ломают скопированную конфигурацию.
| Аспект | Playwright MCP | Объект запуска Puppeteer |
|---|---|---|
Расположение executablePath | browser.launchOptions.executablePath | executablePath верхнего уровня |
Расположение args | browser.launchOptions.args | args верхнего уровня |
| Значение headless | Логическое headless внутри launchOptions | Логическое значение или строка 'shell' |
| Параметры контекста | Отдельный объект browser.contextOptions | Не входят в LaunchOptions; viewport задаётся сервером или кодом в другом месте |
| Сохранение профиля | userDataDir внутри browser | userDataDir на верхнем уровне |
| Подключение к работающему браузеру | cdpEndpoint или remoteEndpoint | browserWSEndpoint или connect() вне LaunchOptions |
Первые две строки объясняют, почему JSON-блок Playwright MCP, вставленный в сервер Puppeteer, ничего не делает: этих ключей нет ни в одном месте, которое просматривает сервер Puppeteer. Третья строка тоньше, поскольку headless: true допустим в обеих системах, и копия может выглядеть работающей при неверной окружающей структуре.
Разделения на контекст здесь нет
Playwright отделяет параметры запуска от параметров контекста, поэтому viewport, локаль и разрешения находятся в другом объекте. В LaunchOptions Puppeteer такого разделения нет: viewport и параметры уровня страницы применяются после запуска через page.setViewport() или дескриптор устройства. Конфигурация, ожидающая, что блок contextOptions передаст локаль, не найдёт его.
Различие важно, когда задача зависит от локали или часового пояса. В Playwright MCP они принадлежат контексту и настраиваются до появления страницы. В Puppeteer они становятся либо аргументами браузера в args, либо вызовами скрипта после запуска, и сервер обязан предоставить способ для одного из вариантов.
Вызовы эмуляции как третий маршрут
page.emulate() и page.setViewport() меняют то, что сообщает страница, после старта браузера, поэтому они становятся третьим местом, откуда может прийти локаль, часовой пояс или viewport. Задача, задающая локаль через args, другую через вызов эмуляции и третью через стандартные значения сервера, имеет три источника и ни одного однозначного ответа.
Управляемое правило здесь состоит в одном источнике на свойство. args выбирается для всего, что браузер должен знать до первого запроса, а вызов эмуляции только для того, что нужно странице после загрузки. Запись маршрута для каждого свойства обязательна, потому что сравнение запуска с локалью в args и запуска с локалью через эмуляцию сопоставляет разные вещи.
Два разных понятия профиля
userDataDir в Puppeteer и аргумент профиля BotBrowser оба описывают постоянное состояние, но означают не одно и то же. userDataDir является каталогом пользовательских данных Chromium, который Puppeteer передаёт браузеру. Профиль BotBrowser представляет собой зашифрованный файл конфигурации, загружаемый двоичным файлом через собственный флаг. Установка одного не задаёт другое, и сервер, предоставляющий только userDataDir, не имеет места для флага профиля, если не передаёт произвольные args.
Передача профиля и режима headless
Флаг профиля является аргументом браузера, поэтому он входит в args одним элементом. Режим headless является параметром Puppeteer, поэтому он входит в headless. Смешение этих двух мест становится следующей ошибкой, которую нужно проверить после путаницы со структурой.
{
"executablePath": "/opt/botbrowser/chrome",
"headless": true,
"args": ["--bot-profile=/etc/botbrowser/profile.enc", "--bot-locale=en-US", "--no-first-run"]
}
Каждый элемент является одним аргументом без оболочного цитирования. Единая строка с пробелами образует один искажённый аргумент. Третий элемент в примере представляет собой обычный флаг Chromium, а не флаг BotBrowser, поскольку args свободно смешивает оба вида: Puppeteer их не различает.
Цитирование, экранирование и слой JSON
Если конфигурация хранится в JSON, аргументы проходят два слоя: экранирование строки JSON и затем вектор аргументов. Путь Windows вида C:\botbrowser\chrome.exe требует экранирования обратных слешей в JSON, а значение с кавычкой требует JSON-экранирования, а не оболочного. Правильный один слой при неверном другом даёт путь, который выглядит корректно в файле и неверно при запуске.
Значения лучше держать свободными от символов, требующих экранирования. Путь профиля без пробелов и кавычек исключает весь этот класс проблем, а абсолютный путь в коротком каталоге проще сверить посимвольно, чем длинный.
Headless, 'shell' и что меняется
Документация Puppeteer указывает, что headless принимает true или строку 'shell', где true выбирает новый режим headless, а 'shell' старый. Различие не косметическое: два режима по-разному компонуют изображение и по-разному сообщают о возможностях через API. Задача, сравнивающая рендеринг или читающая поддержку медиа, должна записывать режим запуска, потому что два запуска в разных режимах не являются одним измерением.
Когда ignoreDefaultArgs меняет ответ
ignoreDefaultArgs принимает true или массив имён флагов. При true Puppeteer перестаёт добавлять стандартные аргументы, и браузер стартует только с содержимым args. При массиве названные стандартные значения отфильтровываются, а остальные сохраняются. Оба варианта меняют итоговый argv, и оба относятся к параметрам, которые сервер может применить самостоятельно.
Эксплуатационное следствие состоит в том, что документированный флаг BotBrowser может быть нейтрализован стандартным флагом Puppeteer, а стандартный флаг Puppeteer может быть удалён через ignoreDefaultArgs. Ни то, ни другое не видно в файле конфигурации, поэтому проверка читает процесс, а не конфигурацию.
pipe и способ связи сервера с браузером
pipe: true передаёт протокол автоматизации через стандартный ввод и вывод вместо открытия WebSocket. Для сервера, запускающего браузер дочерним процессом, это убирает из схемы прослушиваемый порт, что меняет и режимы отказа, и поверхность безопасности. Конфигурация, предполагающая наличие отладочного порта, не действует при установленном pipe, а инструмент, подключающийся через порт, не достигает браузера с каналом.
Транспорт запуска записывается вместе с результатом. Результат, полученный через канал, и результат, полученный через порт, происходят из одного браузера только при совпадении остальной конфигурации, а транспорт является её частью, а не деталью реализации.
Проверка фактически запущенного двоичного файла
Проверка использует три чтения, и они отвечают на разные вопросы. Путь процесса доказывает, какой файл был исполнен. Пользовательский агент описывает то, что сообщает страница, а собственная сборка может настраивать это независимо от двоичного файла. Маркер сборки доказывает наличие возможности, отсутствующей в стандартной сборке.
Сначала читается процесс. На хосте, породившем сервер, находится дочерний процесс, и его исполняемый файл сравнивается с настроенным путём. Сервер, не передавший executablePath, показывает путь внутри каталога кеша Puppeteer, и одно это сравнение решает вопрос без проверок на уровне страницы.
| Чтение | Что доказывает | Чего не доказывает |
|---|---|---|
| Исполняемый файл дочернего процесса | Какой файл запустил сервер | Что профиль загружен |
navigator.userAgent | Что сообщает страница | Какой двоичный файл это создал |
| Маркер сборки | Что конкретная возможность присутствует | Что конфигурация дошла до неё намеченным маршрутом |
| Признак загрузки профиля | Что зашифрованный профиль принят | Что содержимое страницы корректно |
Когда дерево процессов не видно
Сервер внутри контейнера, на удалённом хосте или в песочнице может не показывать дочерние процессы оболочке оператора. В этом случае путь берётся изнутри среды, владеющей процессом, через строку журнала, записываемую сервером, запись /proc или диагностический инструмент платформы. Требование не меняется: наблюдаемый исполняемый файл сравнивается с настроенным там, где наблюдение доступно.
Если недоступно ни одно из этих средств, запасным доказательством становится маркер сборки внутри страницы, и его сила ниже. Маркер доказывает наличие возможности; он не доказывает, что страницу обслуживает процесс, настроенный оператором.
Запись проверки
Настроенный путь, наблюдаемый путь, режим headless, итоговый args и результат маркера сохраняются вместе с отметкой времени. Последующий запуск сравнивает значения без повторного вывода базовой линии. Когда обновление сервера меняет стандартный args, именно эта запись делает изменение видимым.
Что клиент не видит
MCP-клиент видит инструменты, публикуемые сервером. Он не видит объект запуска, дерево процессов и переданные аргументы. Со стороны клиента неверно настроенный сервер неотличим от правильного, поэтому проверка запрашивается через сессию, а записывается вне её.
Таблица симптомов для пути Puppeteer
| Симптом | Причина | Подтверждение | Исправление |
|---|---|---|---|
| Браузер стартует без параметров профиля | Флаг профиля отсутствует в args | В args нет элемента, начинающегося с флага профиля | Добавить по одному элементу массива на флаг |
| Браузер стартует из каталога кеша | executablePath не дошёл до объекта запуска | Путь дочернего процесса находится внутри кеша Puppeteer | Перенести ключ на верхний уровень объекта запуска |
| Сервер завершается с ошибкой запуска | Путь отсутствует или не исполняется | Путь не разрешается для учётной записи сервера | Использовать абсолютный путь, доступный учётной записи |
| Флаги ведут себя иначе после обновления сервера | Сервер изменил стандартный args | Итоговый argv отличается от записанного | Записывать argv и фиксировать версию сервера |
| Инструмент не достигает браузера | Несовпадение транспорта между каналом и портом | Конфигурация задаёт pipe, а инструмент ожидает порт | Выбрать один транспорт для развёртывания |
Вторая строка переживает успешную сессию. Сервер, вернувшийся к встроенному браузеру, правильно отвечает на каждый вызов инструмента, и единственным доказательством остаётся путь процесса.
FAQ
Можно ли использовать конфигурацию Playwright MCP для сервера Puppeteer?
Нет. Playwright MCP вкладывает executablePath и args в browser.launchOptions, а Puppeteer ожидает оба ключа на верхнем уровне объекта запуска. Вставленный блок оставляет сервер Puppeteer без пути к исполняемому файлу, поэтому он запускает встроенный браузер и сообщает об успехе.
Совпадает ли headless: 'shell' с headless: false?
Нет. 'shell' выбирает старую реализацию headless, которая по-прежнему работает без видимого окна, но компонует изображение и сообщает данные иначе, чем новый режим. false запускает браузер с окном. Запись одного из трёх значений сохраняет сравнимость двух измерений.
Заменяет ли userDataDir профиль BotBrowser?
Нет. userDataDir является каталогом пользовательских данных Chromium, который Puppeteer передаёт браузеру. Профиль BotBrowser представляет собой зашифрованный файл конфигурации, загружаемый двоичным файлом через собственный флаг в args. Сервер, предоставляющий только userDataDir, не имеет места для профиля, если не передаёт произвольные аргументы.
Практический вывод
Объект запуска записывается плоским, с executablePath, args и headless на одном уровне, а флаг профиля размещается внутри args отдельным элементом. Затем на хосте читается дочерний процесс, и его исполняемый файл сравнивается с настроенным путём до того, как результат сессии будет принят.
Следующее действие занимает один запуск: стартовать сервер, попросить клиента выполнить одну навигацию и прочитать путь дочернего процесса на хосте. Совпадение с настроенным путём доказывает двоичный файл. Путь внутри кеша Puppeteer означает, что сервер проигнорировал параметр, и каждый результат описывает браузер, который не был выбран.
Sources
Эта статья входит в руководство: Развёртывание и выпуск браузера: операционная карта
Похожие статьи
Настройка Playwright MCP для собственной сборки Chromium
Начало работыБезголовый браузер для ИИ-агентов: запуск и границы инструментов
РазвертываниеСигналы автоматизации и согласованность в Playwright
РазвертываниеАвтоматизация браузера со Stagehand
Начало работыPlaywright и согласованные профили идентичности браузера
Начало работыPuppeteer и BotBrowser: ошибки запуска и профиля
Выполните ту же проверку в BotBrowser
Загрузите профиль, сохраните внутри браузера те сигналы, о которых только что прочитали, и подтвердите результат на своей машине до раскатки.