custom-chrome-dev-mcp
Custom Chrome Dev MCP
Локальный MCP-сервер (Model Context Protocol), позволяющий MCP-клиенту — Claude Code или чему угодно ещё, что умеет говорить через MCP, — управлять вашим настоящим Chrome так, как это сделал бы человек. Никакой телеметрии, сторонних сервисов и облака: всё работает на вашей машине за общим токеном.
Он предоставляет 45 инструментов для навигации, вкладок, восприятия, взаимодействия, доверенного ввода, наблюдаемости и захвата экрана.
Откуда это взялось
Этот проект вдохновлён официальным браузерным MCP от Chrome — сервером Chrome DevTools MCP, опубликованным командой Chrome DevTools, которая первой обосновала, что ИИ-агент должен управлять браузером через DevTools Protocol, а не через распарсенный HTML.
Мы воспроизводим и имитируем эту идею, а не поставляем её. Что мы заимствуем:
Суть — показываем агенту браузер как набор MCP-инструментов.
Восприятие через доступность — отдаём модели компактную a11y-выжимку со стабильными ссылками на элементы, а не простынёй сырого HTML.
Chrome DevTools Protocol как входной слой — настоящие доверенные события вместо синтетических, которые страница может обнаружить и проигнорировать.
Где этот проект намеренно расходится:
Chrome DevTools MCP | Custom Chrome Dev MCP | |
Браузер | По умолчанию запускает собственный Chrome с отдельным каталогом user-data-dir; может также подключаться к запущенному экземпляру через | Всегда управляет только тем Chrome, который у вас уже открыт |
Подключение | Подключается к браузеру через endpoint DevTools Protocol | Chrome-расширение, живущееnce внутри браузера, наведённое на любую выбранную вами вкладку |
Основная цель | Отладка, инспекция и профилирование страницы | Поведение человека, работающего со страницей |
Последняя строка — и есть весь смысл этого репозитория. Chrome DevTools MCP — это инструмент для отладки, который заодно управляет браузером; наш проект — инструмент подражания человеку, который заодно полезен для отладки.
⚠️ Не аффилирован с Google, не одобрен и не поддержан командой Chrome. Это независимая реимплементация, созданная, чтобы учиться на их дизайн и имитировать его. Если нужен официальный поддерживаемый вариант — ото пользуйтесь официальным сервером.
Related MCP server: monkeysee
Проект намеренно сохраняет стиль человека
Большинство средств автоматизации браузера легко обнаружить: синтетические события
с isTrusted=false, фокус, который никогда по-настоящему не переходит, текст,
появляющийся в поле целиком, и стерильный профиль автоматизации без истории.
Каждый такой признак — сигнал.
Этот проект старается убрать эти сигналы:
Ваш реальный профиль. Действия выполются в Chrome, которым вы уже пользуетесь, — ваши cookies, логины, расширения и история. Ничто не выдаёт "новую автоматизацию".
Управляемый ввод.
realClick,realType,press,hoverиdragотправляют события через DevTools Protocol, поэтому страница получает их сisTrusted=true— тем же флагом, который порождают физические мышь и клавиатура.Настоящий фокус. Клик по полю для фокусировки действительно двигает фокус, в правильном порядке, а не присваивает
.valueза спиной страницы.Реальные нажатия клавиш.
pressформирует правильные последовательностиrawKeyDown/char/keyUpс верными кодами клавиш и модификаторами, а не одно синтетическое событиеinput.Проверка считыванием.
fillподтверждает, что поле действительно содержит текст, и агент замечает, когда страница молча отклоняет ввод, — как это сделал бы живой человек.
Цель: страница должна вести себя с агентом, как с человеком за клавиатурой.
Быстрые синтетические инструменты (click, type) остаются на месте — они
быстрее и работают на большинстве сайтов. Когда страница их игнорируulet,
используйте доверенные аналоги.
Как это работает
Один транспорт. MCP-клиент общается с сервером через stdio; сервер ретранслирует сообщения в Chrome-расширение по локальному WebSocket, которым владеет отдельный долгоживущий hub-процесс.
MCP client 1 (Claude) <-stdio-> bin/custom-chrome-dev-mcp.js ─┐
MCP client 2 (Claude) <-stdio-> bin/custom-chrome-dev-mcp.js ─┼─ src/hub.js (127.0.0.1:9876)
MCP client N (Claude) <-stdio-> bin/custom-chrome-dev-mcp.js ─┘ │
│ WebSocket
▼
Chrome extension -> active tabЗачем нужен отдельный hub-процесс. Только один процесс может владеть портом
9876, но одновременно могут быть открыты несколько сессий Claude, и все они
могут хотеть работать с браузером. Поэтому сокет живёт в src/hub.js, а не внутри
какой-либо одной сессии. Каждая сессия подключается к hub под ролью role:"mcp",
расширение — под ролью role:"extension", а hub мультиплексирует обмен между
ними. Первая сессия создаёт hub отсоединённым, поэтому он переживает её;
остальные сессии просто находят процесс уже слушающим порт.
Внутри расширения — трии слоя:
Walker (
page/walker.js) — внедряется в ISOLATED world страницы. Ведёт разрешение элементов, стабильную карту ссылокeNи быстрые синтетические DOM-операции.CDP (
cdp/) —chrome.debuggerдля доверенных вводов,evaluateв контексте страницы, скриншоты всей страницы и буферов консоли/сети.Recording (
recording/) — кадры CDP-screencast, кодируемые в.webmс помощьюMediaRecorderво внеэкранном документе.
🔒 Расширение аутентифицируется на hub с помощью общего токена (
AUTH_TOKEN, одинакового вsrc/config.jsиextension/src/config.js). Hub теряет peed, который предъявит другое значение.
Предварительные требования
Требование | Проверка | |
Node.js | 18 или новее (разработка на 22) |
|
Chrome | Google Chrome или Chromium, любая современная версия |
|
MCP-клиент | Claude Code или что-то ещё, что говорит по MCP через stdio |
|
Никаких глобальных установок, никакой сборки и никакой регистрации. Зависимостей
всего две (@modelcontextprotocol/sdk и ws), и всё остаётся внутри
127.0.0.1.
Локальная настройка
Четыре шага и затем контрольний проход. Заложите пять минут.
1. Клонирование и установка
git clone <your-fork-url> custom-chrome-dev-mcp
cd custom-chrome-dev-mcp
npm installУбедитесь, что с проектом всё в порядке, прежде чем подключать его к Chrome: офлайн-прогон не нуждается в браузере и занимает меньше секунды:
npm testВам нужно 22 passed. Если тест падает — сначала исправьте; всё, что
дальше, без него работать не будет.
2. Загрузите расширение в Chrome
Откройте
chrome://extensions.Включите режим разработчика (переключатель справа вверху).
Нажмите Load unpacked и выберите папку
extension/— именно папку, а неmanifest.jsonвнутри неё.Custom-chrome-dev-mcp появится в списке расширений.
⚠️ Загружайте его в тот профиль Chrome, в котором вы живёте. Chrome хранит расширения отдельно для каждого профицы, поэтому загруженное в «Profile 4» расширение невиден для окна под «Default». Если инструменты перестают видеть вкладки или hub не пишет
extension connected— это первое, что нужно проверить. Вchrome://versionвиден активный Profile Path.
Идентификатор расширения закреплён открытым ключом key в
extension/manifest.json, поэтому он одинаков на каждой машине — ничего копировать
не нужно.
3. Зарегистрируйте MCP-сервер для своего клиента
Используйте CLI и подставьте абсолютный путь к каталогу с репозиторием
(pwd в корне проекта выведет его):
claude mcp add -s user custom-chrome-dev-mcp -- node /ABSOLUTE/PATH/TO/custom-chrome-dev-mcp/bin/custom-chrome-dev-mcp.js-s userрегистрирует сервер для всех ваших проектов;-s local— только для текущего.Регистрировать нужно
bin/custom-chrome-dev-mcp.js— именно этот файл есть точкой входа. Ссылаться наsrc/server.jsне сработает.Путь должен быть абсолютным. Относительный путь будет разрешён относительно каталога, и кубок которого клиент был запущен.
Убедитесь через
claude mcp list— рядом должен появиться✔ Connected.
⚠️ Не редактируйте
~/.claude.jsonвручную. Файл большой, и одна пропущенная боWwish запятая сломает Claude Code. Команда выше делает это безо пасного.
Добавьте сервер в раздел mcpServers:
{
"mcpServers": {
"custom-chrome-dev-mcp": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/custom-chrome-dev-mcp/bin/custom-chrome-dev-mcp.js"]
}
}
}4. Перезапустите MCP-клиент
MCP-клиенты перечисляют инструменты один раз, при запуске, поэтому сервер, зарегистрированный посреди сессии, станет видимы только после перезапуска. Перезапустите Claude — появятся 45 инструментов.
При перезапуске клиент запускает сервер; если на 127.0.0.1:9876 ещё никто не
слушает, сервер порождает src/hub.js.
5. Проверьте все три звена цепочки
Стек: client → server → hub → extension → tab. Проверяйте саму цепочку, а не гадайте, на каком звене обрыв.
# The hub is up, and the extension found it:
tail -f "$TMPDIR/custom-chrome-dev-mcp-hub.log"
# [hub] listening on 127.0.0.1:9876
# [hub] extension connected <- this line is the handshake succeeding
# Who owns the port (should be src/hub.js from THIS repo):
lsof -nP -iTCP:9876 -sTCP:LISTENЗатем попросите у клиента listTabs. JSON-массив открытых вкладок означает,
что все звенья работают. Дополнительно выполните screenshot — PNG сохранится
в ~/Downloads и вернётся обратно в ответе.
Для консоли самого расширения: chrome://extensions → Custom-chrome-dev-mcp →
service worker → Inspect. Ошибки расширения появляются именно там; до
MCP-клиента они не доходят.
6. Смените общий токен перед реальным использованием
AUTH_TOKEN поставляется со значением по умолчанию, одинаково заданным в
src/config.js и extension/src/config.js. Это единственное, что
мешает другому процессу на вашей машине управлять авторизованным браузером.
Выберите свой собственный токен, измените его в обоих файлах (офлайн-тест
проверяет их совпадение) и перезагрузите расширение.
После изменения кода
Две части перезагружаются по-разному, и из-за ошибки здесь вы теряете больше времени, чем на что-либо ещё в проекте:
Какое изменили | Как подхватить изменения |
От | Нажмите reload ↻ у расширения в |
Всё под | Перезапустите MCP-клиент. Процесс сервера живет долго и удерживает старые схемы инструментов. |
| Выполните |
Устранение неполадок
(Всё, что дальше, — о решении типичных проблем.)
Симптом | Причина | Исправление |
| Неверный путь или не та точка входа | Перерегистрируйте с абсолютным путём к |
Инструменты полностью отсутствуют в клиенте | Зарегистрированы в середине сессии | Перезапустите MCP-клиент |
В логе хаба никогда не появляется | Расширение не загружено, загружено в другом профиле Chrome или | Проверьте |
Вызов инструмента зависает, затем истекает по таймауту | Service worker завершился или произошло исключение на стороне расширения | Откройте консоль service worker; нажмите reload ↻ |
Порт | Хаб из другого клона этого проекта занимает порт | Выполните |
Правка в | Chrome всё ещё запускает старую сборку | Нажмите reload ↻ |
|
| Отредактируйте список — он поставляется с заполнителями |
| Сработала защита | Уберите защиту или укажите в ней реальный URL |
Путь к скриншоту отклонён | Запись ограничена каталогом захвата | Используйте имя файла или путь внутри него |
Инструмент нацеливается не на ту вкладку | Фоновая вкладка перехватила фокус | Закрепите рабочую вкладку с помощью |
Конфигурация
Обе переменные окружения необязательны и читаются при запуске файлом src/config.js.
Переменная | По умолчанию | Что делает |
|
| Единственный каталог, в который можно записывать скриншоты и записи. |
|
| Порт хаба. Измените его также в |
Также стоит изменить для реального использования: AUTH_TOKEN, определённый одинаково в
src/config.js и extension/src/config.js. Выберите собственное значение — именно оно не даёт
другому локальному процессу управлять вашим браузером.
Доступные инструменты (45)
Элементы адресуются тремя способами: selector (CSS), ref (стабильный id eN
из snapshotA11y) или name (доступное имя, например, подпись кнопки). «target»
ниже означает любой из этих трёх.
Универсальные параметры, принимаемые каждым инструментом:
tabId— действовать на конкретной вкладке вместо активной в данный момент.frameId(изlistFrames) — действовать внутри конкретного фрейма, включая кросс-доменные iframe, которые верхний документ не может скриптовать.expectUrl— защита: отказать в действии, если URL вкладки не содержит эту подстроку.
Закрепите рабочую вкладку на всю сессию с помощью useTab, чтобы фоновая вкладка
(автовоспроизводящееся видео, всплывающее уведомление) не могла перехватить фокус и направить действие не туда.
Навигация
Инструмент | Аргументы | Описание |
|
| Направить вкладку на URL (заменяет страницу). |
|
| Открыть URL в новой вкладке на переднем плане, не трогая текущую страницу. |
| - | Назад / вперёд по истории. |
|
| Перезагрузить, при необходимости минуя кэш. |
| - | URL / заголовок вкладки (работает и на внутренних страницах). |
|
| Блокировать выполнение, пока вкладка не завершит загрузку. |
Вкладки и фреймы
Инструмент | Аргументы | Описание |
| - | Все открытые вкладки во всех окнах ( |
|
| Сфокусировать вкладку и её окно. |
|
| Закрыть вкладку по id. |
|
| Закрепить рабочую вкладку, чтобы все последующие инструменты нацеливались на неё независимо от фокуса ОС. Опустите |
| - | Снять закрепление; инструменты снова работают с активной вкладкой. |
| - | Все фреймы, включая кросс-доменные, в виде |
Восприятие
Инструмент | Аргументы | Описание |
| - | Компактный accessibility-обзор видимых интерактивных элементов в виде |
| - | Сырой |
| target |
|
| target, | Атрибут с запасным вариантом на живое DOM-свойство ( |
|
| text/href/value/visible для всех совпадений сразу. |
| - |
|
Взаимодействие — синтетическое, быстрое
Недоверенные события, отправляемые обходчиком. Быстро и достаточно для большинства сайтов.
Инструмент | Аргументы | Описание |
| target | Всплывающий |
| target, | Установить значение поля через нативный сеттер (работает с |
| target, | Фокус + установка + чтение обратно. Выбрасывает исключение, если текст не закрепился. Надёжный путь ввода текста — предпочитайте его схеме click-затем-type. |
| target, | Проверить текст (подстроку) и/или точное значение без скриншота → |
| target?, | Прокрутить элемент в зону видимости или окно ( |
| target, | Выбрать вариант |
| target, | Установить чекбокс/радиокнопку, кликая только если она ещё не в нужном состоянии. |
| target |
|
| target или | Опрашивать, пока элемент не разрешится или не появится текстовая подстрока. |
Доверенный ввод и эмуляция — CDP
Настоящие события с isTrusted=true. Они подключают chrome.debugger, из-за чего на вкладке
появляется постоянный жёлтый баннер «being debugged».
Инструмент | Аргументы | Описание |
| target / | Доверенный клик, включая клик правой кнопкой и двойной клик. |
| target?, | Доверенный ввод текста, с фокусировкой на цели, если она указана. |
|
| Доверенные клавиши и комбинации: |
| target / | Переместить реальную мышь над элементом, чтобы вызвать |
|
| Доверенное перетаскивание «нажал-переместил-отпустил». |
|
| Установить файлы на |
|
| Эмуляция области просмотра / устройства для проверки адаптивности. |
|
| Заранее задать ответ для следующего |
| - | Отключить отладчик и убрать баннер. Повторно подключается при следующем вызове CDP. |
Наблюдаемость — CDP, буферизация на вкладку
Запись начинается при подключении отладчика, поэтому перезагрузите страницу после первого вызова CDP, если хотите увидеть активность при загрузке.
Инструмент | Аргументы | Описание |
|
| Буферизованные логи консоли, предупреждения, ошибки и неперехваченные исключения. |
|
| Буферизованные запросы: метод, url, статус, тип, время. |
|
| Один запрос полностью; |
|
| Выполнить JS в реальном контексте страницы через CDP — в обход CSP content-script, который блокирует |
Захват
Сохраняется в каталог захвата (~/Downloads по умолчанию — см.
Конфигурация).
Инструмент | Аргументы | Описание |
|
| Видимая область просмотра в PNG/JPEG — сохраняется на диск и возвращается встроенно с |
|
| Вся прокручиваемая страница за пределами области просмотра, через CDP. |
|
|
|
path — это имя файла или путь внутри каталога захвата. Отсутствующие подпапки
создаются; всё, что разрешается за пределы каталога, отклоняется.
Первый реальный запуск
Шаг 5 настройки доказывает соединение. Этот раздел доказывает самое интересное — что страница видит человека, а не скрипт. Наведите клиент на любую страницу и попросите:
snapshotA11y— компактный обзор с ссылкамиeNдля наведения.realClick {ref:"e3"}— доверенный клик. На вкладке появится жёлтый баннер «идет отладка»; это подключение CDP, и оно должно быть видимым.evaluate {expression:"'ok'"}— JS в контексте страницы, в обход CSP content-script.screenshot— PNG в вашем каталоге захвата и возвращённый встроенно.record {action:"start"}…record {action:"stop", path:"clip.webm"}—.webmвкладки. Не нужен клик по панели инструментов и не нужен жест пользователя; значок на панели инструментов инертен по замыслу и ничего не запускает.detach— убирает баннер.
Чтобы увидеть разницу, которую даёт доверенный путь, установите слушатель и сравните:
// via evaluate
window.__e = []; document.querySelector("button")
.addEventListener("click", e => window.__e.push(e.isTrusted));click сообщает false; realClick сообщает true. Этот контраст — вся суть
проекта, и тестовая линия браузера проверяет именно его.
Запуск тестов
В наборе две линии, и это разделение — суть.
Офлайн-линия — без браузера, работает в CI
npm test # node test/run.mjs --lane=offlineЗавершается значительно быстрее секунды и требует только Node. Она выполняет реальное
рукопожатие MCP в процессе против src/server.js (через внутрипроцессный транспорт
SDK), поэтому проверяет именно ту поверхность, которую сервер реально публикует:
у каждого опубликованного инструмента есть обработчик расширения, и наоборот — та самая ошибка, к которой приглашает зеркальная архитектура
ни одно имя инструмента не заявлено двумя группами обработчиков (они объединяются через spread, поэтому дубликат молча потерялся бы)
каждый инструмент несёт реальное описание и универсальную область видимости
tabId/frameId/expectUrlкаждый инструмент покрыт хотя бы одним тестом — добавьте инструмент без теста, и CI упадёт, без необходимости в браузере
список разрешённых путей захвата действительно отклоняет
.., глубокие.., абсолютные пути и символьные побеги, проверено на реальном резолвересписок запретов проверяется поведенчески — он блокирует то, что заявляет, и не блокирует обычные сайты
хаб привязывается только к loopback, токены совпадают с обеих сторон, манифест не запрашивает излишне широкие разрешения, значок панели инструментов инертен, и ни один
*.pemне закоммичен
Браузерная линия — управляет реальным Chrome
# 1. Disconnect the MCP client (close Claude Code, or disable this server for the run)
# 2. Free port 9876 - the hub is long-lived and outlives the session that spawned it
pkill -f src/hub.js
# 3. Start the suite; it binds 9876 itself and waits for the extension
npm run test:browser
# 4. Reload the extension in chrome://extensions so it connects to the suite⚠️ Шаг 1 не обязателен. Подключённый MCP-клиент перезапускает хаб каждые ~1.2с, когда обнаруживает, что сокет исчез, поэтому он сразу же забирает порт 9876 обратно, и набор умирает с
EADDRINUSE. Убийство хаба, пока клиент ещё подключён, не помогает — клиент просто запускает другой.
Набор поднимает фикстурный сервер и мост, говорящий на том же сетевом протоколе, что и реальный хаб, поэтому успешный прогон проверяет фактический контракт сообщений. Каждый набор зеркалит группу инструментов, и каждый тест начинается со сброшенной фикстурной страницы — ни один тест не наследует мутации другого.
В конце выводится покрытие инструментов, и набор падает, если какой-либо из 45 инструментов остался непроверенным.
Параметры
Команда | Эффект |
| только офлайн-линия — шлюз CI |
| только браузерная линия |
| обе |
| перечислить все наборы и тесты без запуска |
| только тесты, чей набор/имя совпадает |
Структура тестов
test/
├── run.mjs # CLI: lanes, filtering, coverage, reporting
├── lib/
│ ├── runner.js # suite registry, isolation, timeouts
│ ├── assert.js # assertions with diagnostic messages
│ ├── wait.js # eventually() - polling, not fixed sleeps
│ ├── mcp-probe.js # real in-process MCP handshake
│ ├── bridge.js # stands in for the hub; tracks tool coverage
│ ├── fixture-server.js # serves the fixture pages
│ └── page.js # the browser session + per-test reset
├── fixtures/
│ ├── index.html # the fixture page (a real file, with __reset())
│ └── frame.html # child frame, for frameId targeting
└── suites/
├── 01-contract.suite.js # offline
├── 02-security.suite.js # offline
├── 10-navigation.suite.js
├── 20-tabs.suite.js
├── 30-perception.suite.js
├── 40-interaction.suite.js
├── 50-trusted-input.suite.js
├── 60-observability.suite.js
└── 70-capture.suite.jsЗамечания по безопасности
Это расширение может управлять вашим браузером, в котором вы вошли. Прочтите этот раздел.
Только loopback. Хаб привязывается к
127.0.0.1, поэтому он недоступен из LAN — только с процессов на этой машине.Рукопожатие по токену. Пиру необходимо предъявить
AUTH_TOKENпри подключении, иначе хаб его отбрасывает. Измените его с поставляемого по умолчанию (идентичная константа вsrc/config.jsиextension/src/config.js) — именно он мешает другому локальному процессу управлять вашим браузером.Запись файлов ограничена каталогом захвата.
src/capture/capture-path.jsразрешает каждый запрошенный путь и отклоняет всё, что за его пределами, включая обход через..и через символьные подкаталоги. Это важнее, чем кажется: запись по произвольному пути — фактически выполнение кода.Список запретов хостов.
BANLISTвextension/src/config.jsблокирует навигацию и скрипты на чувствительных доменах (банки, PayPal, Gmail). Настройте под свои нужды. Примечание: скриншоты и запись захватывают отрисованные пиксели и не фильтруются списком запретов.Баннер отладчика — это фича. Инструменты CDP подключают
chrome.debugger, показывая постоянную жёлтую полосу «идет отладка». Это ваш видимый сигнал, что кто-то управляет вкладкой.detachубирает его.evaluateвыполняет произвольный JS в реальном контексте страницы.Внутренние страницы запрещены — расширение не может выполнять скрипты на URL
chrome://илиchrome-extension://.Ключ подписи не в этом репозитории. ID расширения закреплён публичным ключом
keyвextension/manifest.json; соответствующий приватный ключ должен оставаться вне системы контроля версий (.gitignoreблокирует*.pem). Он нужен только для переупаковки.crxпод тем же ID — загрузка распакованного расширения его не использует.
Архитектура
Сервер и расширение зеркальны. Каждая группа инструментов в src/tools/ имеет
файл обработчика с тем же именем в extension/src/handlers/. Добавление инструмента
означает изменение ровно этой пары — схема и документация на одной стороне,
реализация на другой.
Группа | Сервер (схема + документация) | Расширение (реализация) |
navigation |
|
|
tabs |
|
|
perception |
|
|
interaction |
|
|
trusted input |
|
|
observability |
|
|
capture |
|
|
Всё остальное — вспомогательная инфраструктура:
bin/custom-chrome-dev-mcp.js- исполняемый файл, который вы регистрируете в вашем MCP- клиенте. Он ничего не делает, кроме запуска сервера.src/config.js/extension/src/config.js- все настраиваемые параметры, по одному файлу на сторону.AUTH_TOKENи порт должны совпадать в обоих.src/relay/hub-client.js- подключается к хабу какrole:"mcp", запускает его, когда отсутствует, и превращает каждый вызов инструмента в запрос/ответ через сокет.src/hub.js- долгоживущий ретранслятор, владеющийws://127.0.0.1:9876. Удерживает один сокет расширения и клиентов каждой сессии и мультиплексирует между ними. Пере-тегирует идентификаторы в канале (они могут конфликтовать между сессиями) и сам завершает работу, если порт уже занят другим хабом.src/capture/capture-path.js- белый список для записи. Каждый путь захвата проходит через него.extension/src/connection.js- сокет хаба плюс heartbeat. Сервис-воркер MV3 уничтожается после ~30 секунд простоя, что молча разрывает сокет; а heartbeat с интервалом менее 30 секунд поддерживает оба в живых, а будильник возрождает воркера после жёсткого завершения.extension/src/tabs.js- на какую вкладку действует вызов (явныйtabId> закреплённая вкладка > активная вкладка), защитаexpectUrlи проверка списка запрещённых.extension/src/walker-bridge.js+extension/src/page/walker.js- внедряемый скрипт в ISOLATED-мире со стабильной системой ссылок на элементы, и единственный модуль, который знает, как до него добраться.extension/src/cdp/-session.js(присоединение/отсоединение,cdp(), центры элементов),keyboard.js(имена клавиш → события клавиш CDP),dialogs.js(политика нативных диалогов),buffers.js(кольцевые буферы консоли и сети, ограниченные 500 на вкладку).extension/src/recording/-chrome.tabCaptureтребует пользовательского жеста, которого у вызова MCP никогда нет, поэтому запись использует вместо этого CDP screencast: кадры JPEG передаются в закадровыйMediaRecorder(у сервис-воркера нет DOM).test/- двухполосный набор: офлайн-шлюз CI, которому не нужен браузер, и браузерная полоса, управляющая реальным Chrome. См. Запуск тестов.
Структура проекта
.
├── bin/
│ └── custom-chrome-dev-mcp.js # executable entry - register THIS with your client
├── src/
│ ├── server.js # composes config + relay + tool registry
│ ├── config.js # port, token, capture dir, timeouts
│ ├── hub.js # long-lived relay owning :9876
│ ├── relay/
│ │ └── hub-client.js # session -> hub socket; call()
│ ├── capture/
│ │ └── capture-path.js # write allowlist for screenshots/recordings
│ └── tools/ # ONE FILE PER TOOL GROUP - the public surface
│ ├── index.js # the registry
│ ├── schemas.js # shared arg shapes + passthrough helper
│ ├── navigation.js
│ ├── tabs.js
│ ├── perception.js
│ ├── interaction.js
│ ├── trusted-input.js
│ ├── observability.js
│ └── capture.js
├── extension/ # Chrome MV3 extension
│ ├── manifest.json
│ └── src/
│ ├── background.js # service worker entry - wiring only
│ ├── config.js # token, banlist, buffer caps, asset paths
│ ├── connection.js # hub socket + MV3 keepalive heartbeat
│ ├── tabs.js # tab resolution, pinning, ban check
│ ├── walker-bridge.js # channel to the injected page script
│ ├── cdp/
│ │ ├── session.js # attach/detach, cdp(), element centres
│ │ ├── keyboard.js # key names -> CDP key events
│ │ ├── dialogs.js # native alert/confirm/prompt policy
│ │ └── buffers.js # console + network ring buffers
│ ├── recording/
│ │ ├── recorder.js # CDP screencast -> offscreen encoder
│ │ ├── offscreen.html
│ │ └── offscreen.js # MediaRecorder host
│ ├── page/
│ │ └── walker.js # injected DOM driver (ISOLATED world)
│ └── handlers/ # MIRRORS src/tools/ - one file per group
│ ├── index.js # the handler table + dispatch
│ ├── navigation.js
│ ├── tabs.js
│ ├── perception.js
│ ├── interaction.js
│ ├── trusted-input.js
│ ├── observability.js
│ └── capture.js
└── test/ # two lanes: offline (CI) + browser
├── run.mjs # CLI entry
├── lib/ # runner, assertions, bridge, fixtures, session
├── fixtures/ # the fixture pages, as real files
└── suites/ # one suite per tool groupБлагодарности
Вдохновлено Chrome DevTools MCP от команды Chrome DevTools. Независимая реализация, не связана с Google, не одобрена и не поддерживается ею.
Лицензия
MIT. Авторское право (c) 2026 Haba Andrei.
Используйте, форкайте, выпускайте. Единственное условие — уведомление об авторском праве и уведомление о разрешении должны сопровождать любую существенную копию.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients to control and interact with the user's real Chrome browser session, leveraging existing logins, cookies, and extensions for AI-driven automation.5MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to drive a real, logged-in Chrome browser for web automation tasks like navigation, clicking, typing, and screenshotting.11MIT
- FlicenseNot gradedqualityCmaintenanceDrive your real, signed-in Chrome browser from any MCP client, enabling browser automation such as navigation, clicking, typing, and screenshots through standard MCP tools.1
- AlicenseCqualityAmaintenanceMCP server for browser automation that drives Chrome via an extension, preserving login state and offering 45 tools for navigation, interaction, scraping, and screenshots.534MIT
Related MCP Connectors
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/HabaAndrei/custom-chrome-dev-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server