La red, con los cuerpos
fetch y XHR se parchean desde adentro de la página, así que los cuerpos de request y de response están de verdad. Sin barra amarilla del depurador, sin extensión, sin medio log.
Un script, y un reporte de bug deja de ser una frase. Llega con la sesión adentro: las llamadas de red con sus cuerpos, la consola, cada clic, y el replay del DOM o el video de la pantalla. Mirala vos — o apuntá un agente de IA por MCP y dejá que la lea entera.
Plan gratis, sin tarjeta. 6 KB gzip en tu página, y no sube nada hasta que alguien reporta un problema.
red (con cuerpos), consola, clics, navegación — 6 KB gzip
<script src="https://app.espejo.dev/sdk/espejo.js" data-key="pk_live_..."></script>
Después, cuando un usuario se choca con algo:
await espejo.report('No me deja guardar el pedido') // → la URL de la sesión subida
El replay, la red, la consola y las interacciones comparten la línea de tiempo. Un 500 deja de ser una línea de log y pasa a ser el botón que alguien apretó un segundo antes.
Espejo corre un servidor MCP en el mismo proceso que la API. Claude Code, claude.ai o cualquier cliente MCP se conecta a POST /mcp con OAuth 2.1 y PKCE; una persona lo aprueba en una pantalla de consentimiento y elige qué proyectos puede ver; y de ahí en más el agente tiene cinco tools de lectura. Puede encontrar la sesión que falló y leer qué pasó adentro sin que nadie abra una consola.
Conectar un agente
$ claude mcp add --transport http espejo https://app.espejo.dev/mcp
Las cinco están detrás de un único scope mcp:read. Una tool sin entrada en la tabla de política no corre, así que agregar un handler nunca alcanza para exponerla: hay que declarar además qué autoridad necesita, en otro archivo, a propósito.
La clave de administrador de la plataforma ve todas las cuentas, así que se la rechaza en la puerta del MCP. Cada conexión tiene atrás una cuenta, un consentimiento y un alcance.
Cada conexión es un permiso que se ve y se revoca, con refresh rotativo y revocación RFC 7009. Se saca el consentimiento y el agente queda afuera.
Las cinco tools
list_recordings Las grabaciones que esta conexión puede ver, de la más nueva a la más vieja. Se filtra por proyecto, por rango de fechas, por texto libre, o sólo las que tienen errores.
get_recording Todo lo que Espejo sabe de una: cuándo corrió, cuánto duró, en qué página y en qué release, sus conteos de error, y qué objetos guardó.
recording_events Qué pasó adentro. Primero el resumen —requests, 4xx/5xx con el clic que los provocó, errores de consola— y después red, consola, interacciones y navegaciones.
recording_frames Links firmados y de vida corta a lo que se puede mirar: el video de pantalla, el replay del DOM de rrweb. Son URLs de Espejo, nunca del bucket, y vencen.
recording_transcript La transcripción guardada de la narración de una grabación, si tiene. Nunca dispara una transcripción — Espejo todavía no las produce.
Hay dos bundles. Elegí uno — esa es toda la integración.
Por defecto no sube nada. El script graba en un anillo en memoria con tope de bytes y manda ese pedazo recién cuando se llama a report(). data-mode="always" sube todas las sesiones — existe, pero no es el default. Es la diferencia entre algo que se puede dejar puesto en producción y algo que te quema el bucket en una semana.
red (con cuerpos), consola, clics, navegación — 6 KB gzip
<script src="https://app.espejo.dev/sdk/espejo.js" data-key="pk_live_..."></script>
todo lo anterior, más replay del DOM con rrweb — 86 KB gzip
<script src="https://app.espejo.dev/sdk/espejo.dom.js" data-key="pk_live_..."></script>
Todo capturado desde la propia página: no hay nada que instalar ni nada que aprobar.
fetch y XHR se parchean desde adentro de la página, así que los cuerpos de request y de response están de verdad. Sin barra amarilla del depurador, sin extensión, sin medio log.
Cada log y cada error, cada interacción descrita —qué se clickeó, jamás qué se tipeó— y cada cambio de URL, en el mismo reloj que todo lo demás.
rrweb reconstruye la página tal como estaba. O grabás la pantalla real, con micrófono, desde un click handler — necesita un gesto del usuario, así que es un botón de tu interfaz.
Cuentas, proyectos, y una clave pública por proyecto que va directo a tu HTML, igual que un DSN de Sentry. La ruta en el bucket la arma siempre el server, nunca la propone el navegador.
Por defecto el nuestro, para que un proyecto arranque en un clic. Apuntarlo a tu propio bucket con tu credencial es una opción de configuración, para quien necesite que las grabaciones no salgan de su cuenta. R2 hoy, S3 después.
Un botón flotante de “reportar un problema” se monta solo, salvo que lo apagues con data-button="off". O llamás a report() desde tu propia interfaz y te devuelve la URL de la sesión.
Una grabación termina en un bucket y en la ventana de contexto de un modelo. Un secreto que se escapa acá no se “borra” después — por eso el redactor corre en el navegador, antes de que salga nada.
Authorization, Cookie, Set-Cookie, x-api-key y proxy-authorization — más cualquier header cuyo nombre traiga “token” o “secret”, que ataja los que nadie listó.
Valores de query y de fragmento que se llamen como un token, password, signature, code, key o credential; el user:pass@ del host; y cualquier cosa con forma de JWT, reconocida por su forma aunque esté sin nombre en medio de un path.
De un input se registra que cambió, jamás con qué. En el replay del DOM van enmascarados todos los inputs, no sólo los de contraseña: un número de tarjeta en un campo de texto común no es menos privado por no ser una contraseña.
data-espejo-block deja un hueco en el replay y además calla los clics de adentro. data-espejo-mask conserva la forma y tapa el texto.
Redactar corre antes de truncar, a propósito: un JSON cortado a la mitad ya no parsea, y un redactor que no puede parsear no puede redactar.
Un plan gratis con el producto entero adentro, y topes en vez de un reloj de prueba.
Gratis
$0
para siempre, sin tarjeta
Todo lo de esta página. El servidor MCP incluido.
El primer tope que se toca manda: ahí se borra la grabación más vieja. Son tres y no uno porque cada uno ataja un abuso distinto: los días atajan al que graba poco y deja todo para siempre, la cantidad al que graba mucho y corto, y los minutos al que graba pocas veces pero largo.
Team
Muy pronto
Topes más altos, tu propio bucket, más gente en la cuenta.
Todavía sin precio. Preferimos no decir nada antes que poner acá un número que no decidimos.
Creá un proyecto, pegá el script, reproducí el bug. Después preguntale a tu agente qué pasó.