Skip to main content
Glama

browserd

Un Chromium con grabación continua y DevTools programables, expuesto a la IA a través de MCP.

No es "Playwright dirigido por un LLM", sino un daemon de navegador que graba todo lo que ve, para que tu agente pueda preguntar por tráfico que ocurrió antes de que pensaras en preguntar.

Node TypeScript MCP Tools Tests


Lo que realmente es

La mayoría de los servidores MCP de navegador envuelven Playwright y dejan que un modelo haga clic en cosas. Eso es una pequeña parte de lo que un desarrollador hace con un navegador abierto.

browserd ejecuta un Chromium real y con interfaz gráfica que puedes usar tú mismo mientras un agente observa por encima del hombro. Mantiene una conexión CDP persistente, registra red, consola, excepciones y navegaciones de forma continua, y las almacena en SQLite. Cuando el modelo finalmente hace una pregunta, consulta una base de datos, no el navegador.

   AI ──MCP──> browserd ──CDP──> Chromium (headed, yours to use)
                  │
                  ├── network recorder ──┐
                  ├── console recorder ──┼──> SQLite + content-addressed blobs
                  ├── page recorder ─────┤
                  └── target manager ────┘        (bodies, traces, heap snapshots)

La diferencia importa. Pregunta a un MCP normal de automatización de navegador «¿por qué falló el pago?» y no tiene nada: la petición ha desaparecido. Pregunta a browserd y tiene el payload, el cuerpo de la respuesta, el error de consola, el stack trace y la línea exacta de código.


Qué puede hacer tu agente

Ver

Capturas de pantalla (viewport / página completa / elemento) devueltas como bloques de imagen reales. Instantáneas de accesibilidad con referencias eNN estables — más baratas y fiables que la visión para decidir en qué hacer clic.

Actuar

Hacer clic, pasar el ratón, escribir, combinaciones de teclas, desplazarse, seleccionar, subir archivos, manejar diálogos. Recurre al envío de eventos táctiles bajo emulación de dispositivo.

Red

Cada petición con todos los encabezados (incluido lo que realmente se envió por el cable), payloads de petición, cuerpos de respuesta, iniciadores, tiempos, cadenas de redirecciones y tramas de WebSocket. La grabación se activa antes de que se ejecute el primer script de la página.

Consola

Salida de console.* y excepciones no capturadas con pilas, conservadas entre navegaciones. Además, Runtime.evaluate con la API de línea de comandos de DevTools ($, $$, $x).

DOM / CSS

Esquemas estructurales, la cascada completa tal como la muestra DevTools, y css.explain_visibility, que nombra la regla que ocultó tu elemento en lugar de entregarte una hoja de estilos.

Depurador

Puntos de ruptura reales con condiciones, ejecución paso a paso, marcos de llamada, cadenas de alcance y evaluación en el marco. Lee una variable local de una pila en pausa.

Almacenamiento

localStorage, sessionStorage, cookies, IndexedDB (lectura y escritura), Cache Storage y cuotas.

Perfilado

Muestreo de CPU, cobertura de JS, trazas transmitidas a disco, instantáneas de heap con diff a nivel de constructor para la caza de fugas, información de proceso/CPU.

Simulación

Un reloj controlado, zona horaria, limitación de CPU, condiciones de red, emulación de dispositivos, geolocalización, deficiencias de visión e inyección de fallos.

Lo que la gente no espera

Viaje en el tiempo. time.run("30m") adelanta el reloj y dispara todos los temporizadores que vencen: un intervalo de 60 segundos se dispara 30 veces, al instante. time.jump("30m") salta hacia adelante disparando cada temporizador una vez, el caso de «cerré el portátil durante tres horas». Distintas clases de errores, distintas herramientas.

time.install({ time: "2030-01-01T00:00:00Z" })   # page now believes it is 2030
time.run({ duration: "30m" })                     # 30 interval ticks, no waiting
time.freeze()                                     # pin it and inspect

Inyección de fallos. Pregunta «¿qué hace la interfaz si Guardar tarda 20 segundos?» y descúbrelo de verdad.

fault.delay({ url: "**/api/save", delay: "20s" })
fault.replace_response({ url: "**/api/user", status: 500, body: {...} })
fault.drop_next({ url: "**/api/payment", count: 1 })

Caza de fugas. Dos instantáneas de heap y un diff, informadas por constructor y señalando los nodos DOM desconectados: la firma clásica de una fuga.

Transferencia humano ↔ IA. inspector.pick activa el selector de elementos real de DevTools para que hagas clic en lo que está roto; el agente devuelve un identificador de nodo. page.highlight funciona en sentido contrario.


Instalación

Requiere Node ≥ 20.11. Chromium se resuelve desde la compilación incluida con Playwright cuando está presente (Chrome oficial 137+ eliminó --load-extension; la compilación incluida todavía lo tiene); si no, desde una instalación del sistema.

git clone <your-remote> browserd && cd browserd
npm install
npm run build

Regístralo en tu cliente MCP

node scripts/install-mcp.mjs

Esto detecta Claude Desktop, Claude Code, Codex CLI, Cursor, Windsurf y VS Code, se integra en su configuración existente (escribiendo primero un .bak) y nunca pisa otros servidores.

node scripts/install-mcp.mjs --print            # show the JSON, change nothing
node scripts/install-mcp.mjs --client codex     # just one client
node scripts/install-mcp.mjs --headless         # auto-launch headless
node scripts/install-mcp.mjs --http --port 7331 # register the HTTP endpoint instead

Clientes compatibles: Claude Desktop, Claude Code, Codex CLI, Cursor, Windsurf, VS Code. Codex usa secciones TOML [mcp_servers.browserd] en lugar de JSON; el instalador edita ese archivo de forma quirúrgica para que los comentarios y tus demás ajustes sobrevivan.

Después confirma que cada cliente realmente puede iniciarlo:

npm run verify-mcp
  OK    Claude Code      174 tools advertised
  OK    Codex CLI        174 tools advertised
  OK    VS Code          174 tools advertised

Esto lee los archivos de configuración reales y completa un handshake MCP con lo que especifiquen, de modo que se detecta una ruta obsoleta o una entrada editada a mano en lugar de darla por supuesta.

O añádelo manualmente:

{
  "mcpServers": {
    "browserd": {
      "command": "node",
      "args": ["/absolute/path/to/browserd/dist/cli.js"]
    }
  }
}

Reinicia tu cliente. No es necesario tener un navegador abierto: la primera llamada a una herramienta que lo necesita lo inicia.

Pruébalo

Pregunta a tu agente:

Abre news.ycombinator.com, muéstrame una captura de pantalla y luego dime cada petición que tardó más de 500 ms y qué devolvió la más lenta.

O, para la propuesta completa:

Ve a mi aplicación en localhost:3000, haz clic en Checkout y dime por qué falla.

Hará una captura de pantalla del fallo, leerá el error de consola, encontrará la petición fallida, te mostrará el payload y el cuerpo de respuesta 400, buscará en las fuentes cargadas la función que llama y te entregará el archivo y la línea.


Ejecutar el daemon directamente

node dist/cli.js                 # MCP over stdio (default)
node dist/cli.js --http          # Streamable HTTP on 127.0.0.1:7331/mcp
node dist/cli.js --tools         # print the tool surface and exit
node dist/cli.js --help

Flag

Significado

--port N

Puerto HTTP (por defecto 7331; 0 elige uno libre)

--host HOST

Dirección de enlace HTTP (por defecto 127.0.0.1no expongas públicamente)

--profile NAME

Perfil usado por los navegadores autoiniciados

--headless

Autoinicio sin interfaz. Por defecto es una ventana visible que también puedes usar

--no-auto-launch

No iniciar nunca implícitamente; exige browser.launch

--log-level LEVEL

trace | debug | info | warn | error

Variables de entorno: AGENTBROWSER_HOME, AGENTBROWSER_PORT, AGENTBROWSER_LOG_LEVEL, AGENTBROWSER_HEADLESS.

El modo HTTP se vincula solo a loopback y valida Origin; este endpoint es el control total del navegador, y una página en la web abierta no debe poder alcanzarlo.


Dos reglas de diseño

1. Graba primero, consulta después

Chromium envía eventos; el daemon los persiste. No hay que preparar nada de antemano y no se pierde ningún evento mientras el modelo piensa. El historial sobrevive a la navegación, al cierre de pestañas y al reinicio del daemon.

Esto es fundamental: los recolectores se suscriben a los eventos CDP antes de habilitar el dominio, y el gestor de objetivos mantiene los nuevos objetivos en waitForDebuggerOnStart hasta que la instrumentación esté activa. Eso es lo que hace que «no perdimos la petición» sea cierto y no probable.

2. Los payloads grandes nunca entran en el contexto

Una respuesta de 200MB se guarda como un blob direccionado por contenido y se devuelve como un identificador de artefacto. El agente lo lee con artifact.search, artifact.read_lines o artifact.json_query (un subconjunto de JSONPath). Lo mismo para trazas, instantáneas de heap, volcados de DOM y exportaciones de consola.

Las herramientas están diseñadas para consultar primero: dom.summary antes que dom.get_html, network.summarize antes que network.list_requests, js.search_source antes que js.get_source.


Humanos e IA en un solo navegador

El navegador tiene interfaz gráfica y es tuyo. browser.set_control_mode arbitra:

modo

significado

observe

La IA lee todo, no cambia nada

shared

Ambos controlan (por defecto)

agent

La IA controla la entrada

paused

IA congelada; las lecturas siguen funcionando

Toda herramienta que muta lo comprueba, incluida la vía de escape cdp.send sin procesar.


La superficie de herramientas

174 herramientas. node dist/cli.js --tools las lista todas.

browser.*      list, launch, connect, status, list_targets, set_control_mode, close
page.*         navigate, screenshot, snapshot, click, type, press, scroll, extract_text,
               wait_for, highlight, dialogs, viewport, frames, tabs
dom.*          summary, query, inspect, get_html, set_html, set_attribute, remove, export
css.*          computed, matched_rules, set_style, stylesheets, explain_visibility
js.*           evaluate, list_scripts, get_source, search_source
console.*      query, exceptions, export, clear
network.*      list_requests, get_request, get_body, summarize, search_bodies,
               list_websockets, ws_messages, export_har, simulate, clear
storage.*      local/session, cookies, indexeddb, caches, usage, export
debugger.*     enable, breakpoints, pause, resume, step, call_frames,
               evaluate_on_frame, inspect_object, wait_for_pause
inspector.*    pick, picked, element, parents, children, snapshot, accessibility_tree
profile.*      start/stop/status (presets: cpu, slow-page, hang, memory-leak, full)
profiler.*     cpu, coverage, trace, long_tasks
memory.*       heap.snapshot, heap.compare, gc, usage
time.*         install, freeze, run, jump, resume, set_fixed_date, set_wall_clock, virtual
device.*       preset, viewport, orientation, reset
environment.*  timezone, locale, color_scheme, reduced_motion, vision, status, reset
fault.*        abort, delay, replace_response, drop_next, modify_headers, list, clear
artifact.*     list, stat, read, read_lines, search, json_query, export
cdp.send       escape hatch to any raw CDP method

Pruebas

npm test                      # build + live MCP suite + HTTP suite
npm run test:live             # 117 checks: real MCP client, real Chromium, local fixture
npm run test:live:headed      # same, with a visible window
npm run test:deep             # 35 checks against a real public site
npm run test:http             # Streamable HTTP transport + origin guard
npm run test:real             # headed narrated walkthrough on live sites

Cada suite lanza el servidor real y conecta un cliente MCP real; las aserciones pasan por tools/call, de modo que la validación de esquema, el cableado de manejadores y las operaciones quedan cubiertos conjuntamente.

Comprueban el comportamiento, no que una llamada devolviera algo:

  • tanto el payload de la petición como el cuerpo de la respuesta de un 400 son legibles

  • una respuesta de 700KB vuelve como artefacto con ~500 caracteres en línea

  • time.run("30m") dispara un intervalo de 60s exactamente 30 veces; time.jump lo dispara una vez

  • una variable local se lee de un marco de llamada en pausa (total=75, tax=15)

  • el modo observe deniega 3/3 mutaciones mientras permite lecturas

  • un HAR exportado se vuelve a parsear como HAR 1.2 válido

  • una instantánea de heap se carga como un .heapsnapshot real

tests/deep-dive.mjs se ejecuta contra Hacker News en vivo: 14 peticiones reales registradas con detalle h2/nginx/IP remoto, un cuerpo de respuesta de 34KB leído del cable, un DOMSnapshot de 1285 nodos, un árbol de accesibilidad de 1603 nodos y un delta de heap de 8MB detectado.


Estructura

src/
  cdp/        persistent WebSocket, flat-session multiplexing
  browser/    launcher, target manager (auto-attach + debugger hold), registry, faults
  collect/    network, console, page and execution-context recorders
  store/      SQLite schema, blob store, artifact store
  ops/        the actual capabilities, independent of MCP
  mcp/        tool definitions and server wiring
  cli.ts      stdio / HTTP entry point
tests/        live MCP suites
scripts/      install-mcp.mjs

MCP es una interfaz hacia el daemon, no el daemon en sí. src/index.ts exporta el núcleo para que una CLI, una capa REST o un banco de pruebas puedan manejarlo directamente.

Los datos viven en ~/.agent-browser (AGENTBROWSER_HOME para moverlos): browserd.db, blobs/, artifacts/, profiles/, logs/.


Notas de seguridad

  • Vincula solo loopback. Este endpoint es control total de un navegador que mantiene tus sesiones iniciadas.

  • Los perfiles de navegador en ~/.agent-browser/profiles contienen cookies y tokens de sesión. Los cuerpos grabados contienen lo que devolvieron las páginas que visitaste. Ambos están en gitignore; mantenlos así.

  • --net-log-capture-mode=Everything puede incluir bytes crudos del cable. Úsalo solo con tráfico que sea tuyo.

  • cdp.send es CDP sin restricciones, limitado solo por el modo de control.


Límites conocidos

  • Debugger.setScriptSource la edición en vivo ya no está en el Chromium actual — edita el código y vuelve a cargar.

  • Network.getRequestPostData puede omitir archivos en subidas multipart, por lo que «cada byte de cada subida» no está garantizado solo con esa ruta. Inicia con capture_netlog para detalle a nivel de pila (DNS, sockets, TLS).

  • El reloj controlado es un shim de temporizador falso instalado mediante addScriptToEvaluateOnNewDocument, no la API Clock de Playwright, ya que el demonio habla CDP puro. time.virtual expone la política de tiempo virtual propia de Chromium; los dos no pueden combinarse en un mismo objetivo y el demonio se niega a apilarlos.

  • La emulación táctil deliberadamente no establece Emulation.setEmitTouchEventsForMouse: esa marca hace que Chromium deje de reconocer Input.dispatchMouseEvent permanentemente. page.click sintetiza toques en su lugar.

  • ontouchstart in window se decide al crear el documento, por lo que aparece después de una recarga. navigator.maxTouchPoints está activo inmediatamente.

  • Target.openDevTools (devtools.open) es experimental y algunas compilaciones lo rechazan.

  • La emulación de sensores no está implementada. La lectura/escritura en bruto de la memoria de proceso está fuera de alcance — eso requiere un adaptador de depuración aparte.


Licencia

MIT

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Live browser debugging for AI assistants — DOM, console, network via MCP.

  • A paid remote MCP for AI agent browser DevTools MCP, built to return verdicts, receipts, usage logs,

  • A paid remote MCP for AI agent browser MCP session, built to return verdicts, receipts, usage logs,

View all MCP Connectors

Latest Blog Posts

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/Kawai-Senpai/Browsered'

If you have feedback or need assistance with the MCP directory API, please join our Discord server