custom-chrome-dev-mcp
Custom Chrome Dev MCP
Un servidor MCP (Model Context Protocol) solo local que permite que un cliente MCP - Claude Code, o cualquier otra cosa que hable MCP - controle tu Chrome real de la misma manera que lo haría una persona. Sin telemetría, sin servicios de terceros, sin nube: todo se ejecuta en tu máquina detrás de un token compartido.
Expone 45 herramientas en navegación, pestañas, percepción, interacción, entrada confiable, observabilidad y captura.
De dónde viene esto
Este proyecto está inspirado en el MCP de navegador oficial de Chrome - el Chrome DevTools MCP servidor publicado por el equipo de Chrome DevTools, que fue el primero en argumentar que un agente de IA debería controlar un navegador a través del Protocolo DevTools en lugar de a través de HTML extraído.
Estamos replicando e imitando esa idea, no distribuyéndola. Lo que tomamos prestado:
La premisa - exponer el navegador a un agente como un conjunto de herramientas MCP.
Percepción basada en accesibilidad - entregar al modelo un esquema de accesibilidad compacto con referencias de elementos estables en lugar de un muro de HTML crudo.
El Protocolo DevTools de Chrome como capa de entrada - eventos reales y confiables en lugar de sintéticos que una página puede detectar e ignorar.
Donde este proyecto se desvía deliberadamente:
Chrome DevTools MCP | Custom Chrome Dev MCP | |
Navegador | Por defecto lanza su propio Chrome con un directorio de datos de usuario dedicado; también puede conectarse a una instancia en ejecución mediante | Solo controla el Chrome que ya tienes abierto |
Conexión | Se conecta al navegador a través del endpoint del Protocolo DevTools | Una extensión de Chrome que vive dentro del navegador, apuntando a la pestaña que elijas |
Objetivo principal | Depurar, inspeccionar y perfilar una página | Comportarse como un humano que usa esa página |
Esa última fila es el punto central de este repositorio. Chrome DevTools MCP es una herramienta de depuración que resulta que controla un navegador; esto es una herramienta de imitación-de-una-persona que resulta útil para depurar.
⚠️ No está afiliado, respaldado ni soportado por Google o el equipo de Chrome. Esta es una reimplementación independiente creada para aprender de su diseño e imitarlo. Usa el servidor oficial si quieres la versión soportada.
Related MCP server: monkeysee
Mantiene deliberadamente el estilo de un humano
La mayoría de la automatización de navegadores es trivialmente detectable: eventos sintéticos con
isTrusted=false, foco que nunca se mueve realmente, texto que aparece en un campo de una sola vez,
un perfil de automatización impecable sin historial. Cada uno de esos es una señal.
Este proyecto intenta eliminar esas señales:
Tu perfil real. Las acciones se ejecutan en el Chrome que ya usas: tus cookies, inicios de sesión, extensiones e historial. Nada que marcar como "automatización nueva".
Entrada confiable.
realClick,realType,press,hoverydragse envían a través del Protocolo DevTools, por lo que la página recibe eventos conisTrusted=true- el mismo indicador que produce un mouse y teclado físicos.Foco genuino. Hacer clic para enfocar un campo realmente mueve el foco, en orden, en lugar de asignar
.valuea espaldas de la página.Pulsaciones de teclas reales.
pressemite secuencias adecuadas derawKeyDown/char/keyUpcon códigos de tecla y modificadores correctos, no un único evento sintético deinput.Verificación de lectura.
fillconfirma que el campo realmente contiene el texto, para que el agente note cuando una página rechazó silenciosamente la entrada, como lo haría una persona.
El objetivo: una página debe comportarse para el agente exactamente como se comporta para alguien sentado frente al teclado.
Las herramientas sintéticas rápidas (click, type) siguen ahí: son más rápidas y funcionan en la
mayoría de los sitios. Cuando una página las ignora, recurre a las equivalentes confiables.
Cómo funciona
Un transporte. El cliente MCP habla con el servidor a través de stdio; el servidor retransmite a una extensión de Chrome a través de un WebSocket local propiedad de un proceso hub pequeño y de larga duración.
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 tabPor qué un proceso hub separado. Solo un proceso puede ser dueño del puerto 9876, pero puedes
tener varias sesiones de Claude abiertas y todas pueden querer el navegador. Así que el socket
vive en src/hub.js en lugar de dentro de cualquier sesión. Cada sesión se conecta al
hub como role:"mcp", la extensión se conecta como role:"extension", y el hub
multiplexa entre ellos. La primera sesión que se inicia genera el hub de forma separada, por lo que
sobrevive a esa sesión; las sesiones posteriores lo encuentran ya escuchando.
Dentro de la extensión hay tres capas:
Walker (
page/walker.js) - se inyecta en el mundo AISLADO de la página. Es dueño de la resolución de elementos, el mapa de referencias estableseN, y las operaciones sintéticas rápidas del DOM.CDP (
cdp/) -chrome.debuggerpara entrada confiable,evaluateen el contexto de la página, capturas de pantalla de página completa, y los buffers de consola/red.Grabación (
recording/) - fotogramas de screencast de CDP codificados a.webmpor unMediaRecorderen un documento fuera de pantalla.
🔒 La extensión se autentica con el hub mediante un token compartido (
AUTH_TOKEN, idéntico ensrc/config.jsyextension/src/config.js). El hub descarta cualquier par que presente un valor diferente.
Requisitos previos
Requisito | Comprobación | |
Node.js | 18 o más reciente (desarrollado en 22) |
|
Chrome | Google Chrome o Chromium, cualquier versión reciente |
|
Un cliente MCP | Claude Code, o cualquier otra cosa que hable MCP sobre stdio |
|
Sin instalaciones globales, sin paso de compilación, sin servicio al que registrarse. Dos dependencias
de ejecución (@modelcontextprotocol/sdk y ws) y todo permanece en 127.0.0.1.
Configuración local
Cuatro pasos, luego una verificación. Presupuesta cinco minutos.
1. Clonar e instalar
git clone <your-fork-url> custom-chrome-dev-mcp
cd custom-chrome-dev-mcp
npm installConfirma que el árbol está sano antes de conectar cualquier cosa a Chrome: la vía sin conexión no necesita navegador y tarda menos de un segundo:
npm testQuieres 22 passed. Si falla, arréglalo antes de continuar; nada más adelante funcionará.
2. Cargar la extensión en Chrome
Abre
chrome://extensions.Activa Modo de desarrollador (interruptor en la parte superior derecha).
Haz clic en Cargar descomprimida y selecciona la carpeta
extension/- la carpeta en sí, nomanifest.jsondentro de ella.Custom-chrome-dev-mcp aparece en la lista.
⚠️ Cárgala en el perfil de Chrome en el que realmente navegas. Chrome mantiene extensiones por perfil, por lo que una extensión cargada en "Perfil 4" es invisible para la ventana que se ejecuta bajo "Default". Si las herramientas luego informan que no hay pestañas, o el hub nunca registra
extension connected, esto es lo primero que debes verificar.chrome://versionmuestra la Ruta del perfil activa.
El ID de la extensión está fijado por la key pública en extension/manifest.json, por lo que es
idéntico en todas las máquinas: no hay nada que copiar entre configuraciones.
3. Registrar el servidor MCP con tu cliente
Usa la CLI - sustituye la ruta absoluta donde clonaste el repositorio (pwd en la raíz del
proyecto la imprime):
claude mcp add -s user custom-chrome-dev-mcp -- node /ABSOLUTE/PATH/TO/custom-chrome-dev-mcp/bin/custom-chrome-dev-mcp.js-s userlo registra para todos tus proyectos;-s locallo limita a este.Registra
bin/custom-chrome-dev-mcp.js- ese archivo es el punto de entrada. Apuntar asrc/server.jsno funcionará.La ruta debe ser absoluta. Una ruta relativa se resuelve contra el directorio desde el que el cliente se lanzó.
Confirma con
claude mcp list- quieres un✔ Connectedjunto a él.
⚠️ No edites manualmente
~/.claude.json. Es grande, y una coma mal colocada rompe Claude Code por completo. El comando anterior lo edita de forma segura.
Agrega el servidor bajo mcpServers:
{
"mcpServers": {
"custom-chrome-dev-mcp": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/custom-chrome-dev-mcp/bin/custom-chrome-dev-mcp.js"]
}
}
}4. Reiniciar el cliente MCP
Los clientes MCP enumeran las herramientas una vez, al inicio: un servidor registrado a mitad de sesión es invisible hasta que reinicies. Reinicia Claude y aparecerán las 45 herramientas.
Al reiniciar, el cliente lanza el servidor, que genera src/hub.js si nada está ya
escuchando en 127.0.0.1:9876.
5. Verificar los tres eslabones de la cadena
La pila es cliente → servidor → hub → extensión → pestaña. Verifícala de extremo a extremo en lugar de adivinar qué eslabón está caído.
# 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:LISTENLuego pide a tu cliente listTabs. Un array JSON de tus pestañas abiertas significa que cada
eslabón funciona. Continúa con screenshot - un PNG aterriza en ~/Downloads y vuelve
en línea.
Para la consola propia de la extensión: chrome://extensions → Custom-chrome-dev-mcp →
service worker → Inspect. Ahí es donde aparecen los errores del lado de la extensión; nunca
llegan al cliente MCP.
6. Cambiar el token compartido antes del uso real
AUTH_TOKEN viene con un valor predeterminado, definido de manera idéntica en src/config.js y
extension/src/config.js. Es lo único que impide que otro proceso en tu máquina controle tu navegador
con sesión iniciada. Elige tu propio valor, cámbialo en ambos archivos (una prueba sin conexión
verifica que coincidan) y recarga la extensión.
Después de cambiar código
Las dos mitades se recargan de manera diferente, y equivocarse en esto pierde más tiempo que cualquier otra cosa en el proyecto:
Editaste | Para que se aplique |
Cualquier cosa bajo | Haz clic en recargar ↻ en la extensión en |
Cualquier cosa bajo | Reinicia el cliente MCP. El proceso del servidor es de larga duración y mantiene los esquemas de herramientas antiguos. |
|
|
Solución de problemas
Síntoma | Causa | Solución |
| Ruta incorrecta, o no es el punto de entrada | Vuelve a registrarlo con la ruta absoluta a |
Faltan herramientas en el cliente por completo | Registradas a mitad de sesión | Reinicia el cliente MCP |
El registro del hub nunca dice | La extensión no está cargada, está cargada en otro perfil de Chrome, o | Comprueba |
Una llamada a herramienta se cuelga y luego expira | El service worker murió, o hubo una excepción en la extensión | Abre la consola del service worker; haz clic en reload ↻ |
El puerto | Un hub de otra copia de este proyecto está ocupando el puerto |
|
Una edición en | Chrome sigue ejecutando la versión antigua | Haz clic en reload ↻ |
|
| Edita la lista: viene con entradas de ejemplo |
| La protección | Elimina la protección, o apúntala a la URL real |
Ruta de captura de pantalla rechazada | Las escrituras están restringidas al directorio de captura | Usa un nombre de archivo o una ruta dentro de él |
Una herramienta apunta a la pestaña equivocada | Una pestaña en segundo plano robó el foco | Fija la pestaña de trabajo con |
Configuración
Ambas son variables de entorno opcionales que src/config.js lee al arrancar.
Variable | Por defecto | Qué hace |
|
| El único directorio donde se pueden escribir capturas de pantalla y grabaciones. |
|
| Puerto del hub. Cámbialo también en |
También vale la pena cambiarlo para uso real: AUTH_TOKEN, definido de forma idéntica en
src/config.js y extension/src/config.js. Elige tu propio valor: es lo que impide
que otro proceso local controle tu navegador.
Herramientas disponibles (45)
Los elementos se apuntan de tres formas: selector (CSS), ref (un id eN estable
de snapshotA11y), o name (nombre accesible, p. ej. la etiqueta de un botón). "target"
abajo significa cualquiera de esas tres.
Parámetros universales, aceptados por todas las herramientas:
tabId- actuar sobre una pestaña específica en lugar de la activa del entorno.frameId(delistFrames) - actuar dentro de un frame específico, incluidos iframes de origen cruzado que el documento superior no puede scriptear.expectUrl- una protección: rechaza la acción a menos que la URL de la pestaña contenga esta subcadena.
Fija una pestaña de trabajo para toda la sesión con useTab para que una pestaña en segundo plano (un
vídeo con reproducción automática, un popup de notificación) no pueda robar el foco y desviar una acción.
Navegación
Herramienta | Args | Descripción |
|
| Apunta la pestaña a una URL (reemplaza la página). |
|
| Abre una URL en una pestaña nueva en primer plano, dejando la página actual intacta. |
| - | Historial: atrás / adelante. |
|
| Recarga, opcionalmente omitiendo la caché. |
| - | La URL / el título de la pestaña (funciona también en páginas internas). |
|
| Bloquea hasta que la pestaña termine de cargar. |
Pestañas y frames
Herramienta | Args | Descripción |
| - | Cada pestaña abierta en todas las ventanas ( |
|
| Enfoca una pestaña y su ventana. |
|
| Cierra una pestaña por su id. |
|
| Fija la pestaña de trabajo para que todas las herramientas posteriores la apunten independientemente del foco del SO. Omite |
| - | Libera la fijación; las herramientas vuelven a la pestaña activa. |
| - | Cada frame, incluidos los de origen cruzado, como |
Percepción
Herramienta | Args | Descripción |
| - | Esquema de accesibilidad compacto de los elementos interactivos visibles como |
| - |
|
| target |
|
| target, | Un atributo, con respaldo en la propiedad DOM viva ( |
|
| text/href/value/visible de todas las coincidencias a la vez. |
| - |
|
Interacción: sintética, rápida
Eventos no confiables despachados por el walker. Rápida y suficiente para la mayoría de los sitios.
Herramienta | Args | Descripción |
| target | Clic de |
| target, | Establece el valor de un campo mediante el setter nativo (maneja |
| target, | Enfocar + establecer + leer de vuelta. Lanza un error si el texto no se mantuvo. La vía fiable para escribir texto: prefierela sobre clic-y-luego-escribir. |
| target, | Verifica texto (subcadena) y/o valor exacto sin captura de pantalla → |
| target?, | Desplaza un elemento hasta hacerlo visible, o la ventana ( |
| target, | Elige una opción de |
| target, | Marca una casilla o botón de radio, haciendo clic solo si no está ya marcado. |
| target |
|
| target o | Sondea hasta que un elemento se resuelva o aparezca una subcadena de texto. |
Entrada confiable y emulación: CDP
Eventos reales con isTrusted=true. Estos adjuntan chrome.debugger, que muestra un
banner amarillo persistente de "being debugged" en la pestaña.
Herramienta | Argumentos | Descripción |
| target / | Clic de confianza, incluidos el clic derecho y el doble clic. |
| target?, | Inserción de texto de confianza; si se pasa |
|
| Teclas y combinaciones de confianza: |
| target / | Mueve el ratón real sobre un elemento para disparar |
|
| Arrastrar y soltar de confianza (pulsar, mover y soltar). |
|
| Establece archivos en un |
|
| Emula un viewport / dispositivo para comprobar el diseño responsivo. |
|
| Preconfigura una respuesta para el siguiente |
| - | Desconecta el depurador y elimina el banner. Se vuelve a conectar en la siguiente llamada CDP. |
Observabilidad - CDP, con búfer por pestaña
La captura comienza cuando se conecta el depurador, así que recarga la página después de la primera llamada CDP si quieres ver la actividad desde el momento de la carga.
Herramienta | Argumentos | Descripción |
|
| Logs de consola, advertencias, errores y excepciones no capturadas, con búfer. |
|
| Solicitudes con búfer: método, url, estado, tipo, tiempo. |
|
| Una solicitud completa; |
|
| Ejecuta JS en el contexto real de la página mediante CDP - evita el CSP del content script que bloquea |
Captura
Se guarda en el directorio de captura (~/Downloads/ por defecto; consulta
Configuración).
Herramienta | Argumentos | Descripción |
|
| Viewport visible como PNG/JPEG - se guarda en disco y se devuelve en línea con |
|
| Toda la página desplazable más allá del viewport, mediante CDP. |
|
|
|
path es un nombre de archivo o una ruta dentro del directorio de captura. Las subcarpetas
que faltan se crean; cualquier cosa que resuelva fuera del directorio queda rechazada.
Una primera ejecución real
El paso 5 de la configuración prueba el conexionado. Aquí está la parte interesante: que una página vea una persona en lugar de un script. Apunta tu cliente a cualquier página y pide:
snapshotA11y- el esquema compacto, con referenciaseNpara apuntar los blancos.realClick {ref:"e3"}- un clic de confianza. En la pestaña aparece un banner amarillo "siendo depurado"; esa es la conexión CDP, y es intencionalmente visible.evaluate {expression:"'ok'"}- JS en el contexto de la página, evitando el CSP del content script.screenshot- un PNG en tu directorio de captura y devuelto en línea.record {action:"start"}…record {action:"stop", path:"clip.webm"}- un.webmde la pestaña. No hace falta clic en la barra de herramientas ni gesto del usuario; el icono de la barra es inerte por diseño y no inicia nada.detach- quita el banner.
Para ver la diferencia que hace la vía de confianza, instala un listener y compara:
// via evaluate
window.__e = []; document.querySelector("button")
.addEventListener("click", e => window.__e.push(e.isTrusted));click informa false; realClick informa true. Ese contraste es el sentido del proyecto, y la vía de pruebas de navegador lo comprueba directamente.
Ejecutar los tests
La suite tiene dos vías, y la división es la clave.
Vía sin conexión - sin navegador, se ejecuta en CI
npm test # node test/run.mjs --lane=offlineCompleta en poco menos de un segundo y no necesita más que Node. Ejecuta un handshake MCP real en proceso contra src/server.js (a través del transporte en memoria del SDK), por lo que verifica la superficie que el servidor realmente publica:
cada herramienta publicada tiene un handler en la extensión, y viceversa - el fallo que la arquitectura espejo invita a cometer
ningún nombre deherramienta es reclamado por dos grupos de handlers (se fusionan por spread, así que un duplicado se perdería en silencio)
cada herramienta lleva una descripción real y el ámbito universal
tabId/frameId/expectUrlcada herramienta está ejercitada por al menos un test - añade una herramienta sin test y CI falla, sin necesidades un navegador
la allowlist de rutas de captura rechaza de verdad
.., los..en profundidad, rutas absolutas y escapes mediante symlink, probado contra el resolver realla lista de exclusión se comprueba por comportamiento: bloquea lo que dice bloquear y no sobrebloquea sitios ordinarios
el hub enlace solo loopback, los tokens coinciden en ambos lados, el manifest no pide permisos demasiado amplios, el icono de la barra es inerte, y no se incluye ningún
*.pem
Vía de navegador - maneja Chrome real
# 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⚠️ El paso 1 no es opcional. Un cliente MCP conectado relanza el hub cada ~1.2s siempre que ve el socket desaparecido, así que recupera el puerto 9876 al momento y la suite muere con
EADDRINUSE. Matar el hub mientras hay cliente conectado no ayuda: el cliente simplemente abre otro nuevo.
La suite levanta un servidor fixture y un puente que habla el mismo protocolo de red que el hub de verdad, de modo que una ejecución que acierta ejercita el contrato del mensaje real. Cada suite refleja un grupo de herramientas, y cada test perfecciona el mismo fixture reset - no test recoge las mutaciones de otro.
Al final imprir la cobertura de herramientas y falla si alguna de las 45 herramientas quedó sin probarse.
Opciones
Comando | Efecto |
| solo la vía sin conexión - el control de CI |
| solo la vía de navegador |
| ambas |
| lista todas las suites y tests sin ejecutarlos |
| solo tests cuya suite/nombre coincide con el patrón |
Estructura de los tests
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.jsNotas de seguridad
Esta extensión puede controlar tu navegador con la sesión iniciada. Lee esta sección.
Solo loopback. El hub se vincula a
127.0.0.1, por lo que no es alcanzable desde la LAN: solo desde procesos de esta máquina.Handshake de token. Cualquier compañero debe mostrar
AUTH_TOKENal conectar o el hub lo descarta. Cámbialo respecto al valor incluidosed (constante idéntica ensrc/config.jsyextension/src/config.js): es lo que evita que otro proceso local maneje tu navegador.Escrituras de archivos confinadas al directorio de captura.
src/capture/capture-path.jsresuelve cada ruta solicitada y rechaza cualquier cosa fuera de él, incluida la travesía con..y mediante subdirectoriossymlink. Esto importa más de lo que parece: escrituras incontroladas en rutas son efectivamente ejecución de código.Lista de bloquear
BANLISTenextension/src/config.jsbloquea la navegación y scripting en sitios delicados (banca, PayPal, Gmail). Adáptala a tus necesidades. Nota: las capturas y grabaciones generan píxeles render mix y no las filtra la lista.El banner de depurador es una característica. Las herramientas CDP invocan
chrome.debugger, mostrando una barra amarilla persistente "siendo depurado". Esta es tu señal visible de que algo está conduciendo la pestaña.detachlo elimina.evaluateejecuta JS arbitrario en Contexto real de la página.Las páginas internas no están disponibles: la extensión no puede ejecutar scripts en URLs
chrome://ochrome-extension://.La clave de firma no está en el repo. El ID de la extensión queda fijado por la clave pública
keyenextension/manifest.json; la privada correspondiente debe estar fuera del control de versiones (.gitignorebloquea*.pem). Solo vale para reempaquetar un.crxcon el mismo ID: cargar "unpacked" no la utiliza.
Arquitectura
El servidor y la extensión son modulares. Cada grupo de herramientas en src/tools/ tiene un archivo de handlers del mismo nombre en extension/src/handlers/. Añadir una herramienta significa tocaragar exactamente ese par: su esquema y docs a un lado, su implementación al otro.
Grupo | Servidor (esquema + docs) | Extensión (implementación) |
navigation |
|
|
tabs |
|
|
perception |
|
|
interaction |
|
|
trusted input |
|
|
observability |
|
|
capture |
|
|
lo demás es infraestructura de apoyo:
bin/custom-chrome-dev-mcp.js- el ejecutable que registras en tu cliente MCP. No hace nada más que iniciar el servidor.src/config.js/extension/src/config.js- todos los parámetros configurables, un archivo por lado.AUTH_TOKENy el puerto deben coincidir en los dos.src/relay/hub-client.js- se conecta al hub con el rolrole:"mcp", lo inicia cuando no está presente y convierte cada llamada de herramienta en una solicitud/respuesta a través del socket.src/hub.js- el relay de larga vida propietario dews://127.0.0.1:9876. Mantiene el único socket de la extensión junto con el cliente de cada sesión y multiplexa entre ellos. Re-etiqueta los IDs en la comunicación (pueden colisionar entre sesiones) y se sale por sí mismo si el hub ya posee el puerto.src/capture/capture-path.js- la lista blanca de escritura. Cada ruta de captura pasa por él.extension/src/connection.js- el socket del hub y el latido. Un service worker de MV3 se termina tras ~30s de inactividad, lo que deja caer silenciosamente el socket; un latido de menos de 30s mantiene ambos con vida, y una alarma revive al worker tras un cierre forzado.extension/src/tabs.js- qué pestaña actúa en una llamada (tabIdexplícito > pestaña fijada > pestaña activa), la protección deexpectUrly la comprobación de la lista negra.extension/src/walker-bridge.js+extension/src/page/walker.js- el script inyectado en el mundo ISOLATED con el sistema estable de referencias a elementos, y el único módulo que sabe cómo llegar a él.extension/src/cdp/-session.js(adjuntar/separar,cdp(), centros de elementos),keyboard.js(nombres de teclas → eventos de teclado CDP),dialogs.js(política de diálogos nativos),buffers.js(búferes circulares de consola y red, con un límite de 500 por pestaña).extension/src/recording/-chrome.tabCapturenecesita una interacción del usuario que una llamada MCP nunca tiene, así que la grabación usa el screencast de CDP en su lugar: fotogramas JPEG enviados a unMediaRecorderfuera de pantalla (el service worker no tiene DOM).test/- suite de dos carriles: una verificación de CI sin conexión que no necesita navegador, y una vía de navegador que controla Chrome real. Consulta Ejecución de las pruebas.
Estructura del proyecto
.
├── 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 groupCréditos
Inspirado por Chrome DevTools MCP del equipo de Chrome DevTools. Reimplementación independiente, no afiliada a Google, ni avalada ni respaldada por Google.
Licencia
MIT. Copyright (c) 2026 Haba Andrei.
Úsalo, hazle un fork, publícalo. La única condición es que el aviso de copyright y el aviso de permiso viajen con cualquier copia sustancial.
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