Files
web_scraping/CAPABILITIES_TODO.md
T
egutierrez 618e3b0295 chore: auto-commit (13 archivos)
- CAPABILITIES_TODO.md
- demo_e2e/RESUMEN.md
- demo_e2e/results/prueba_1_quotes.json
- demo_e2e/results/prueba_2_perceive.json
- demo_e2e/results/prueba_3_search.json
- demo_e2e/results/prueba_4_login_session.json
- demo_e2e/results/prueba_5_books.json
- demo_e2e/results/prueba_6_session_storage.json
- demo_e2e/results/prueba_7_find_honesto.json
- demo_e2e/results/prueba_8_verificacion.json
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-06 13:20:36 +02:00

42 KiB
Raw Blame History

title, artefacto, created, updated, status, related_issues, related_flows
title artefacto created updated status related_issues related_flows
Capacidades de navegador (CDP) + construcción del MCP full-CDP project · projects/web_scraping 06/06/2026 00:00 06/06/2026 09:00 in_progress

Objetivo

Dos objetivos encadenados:

  1. Inventario — mapear todas las capacidades de control de navegador del proyecto web_scraping contra el dominio browser del registry (funciones Go, Bash y pipelines Python) y la app script_navegador. Marcar qué está cubierto, qué está a medias y qué falta.
  2. MCP full-CDP — construir un servidor MCP (browser_mcp) que exponga TODAS estas capacidades como tools, para que cualquier agente Claude controle el navegador de punta a punta. Los gaps que faltan se construyen en paralelo con varios fn-constructor, y el MCP los envuelve a medida que aparecen.

Este documento es la lista de trabajo viva del proyecto: cada gap es una tarea candidata a delegar a fn-constructor, y cada función del registry es una tool candidata del browser_mcp.

Convención de estado por capacidad:

  • [x] Cubierto — hay función(es) del registry dedicadas y probadas.
  • [~] Parcial — se puede hacer pero indirecto (vía cdp_evaluate) o incompleto (falta parte del CRUD).
  • [ ] Falta — no existe ninguna función para esto.

Resumen ejecutivo

# Capacidad pedida Estado Notas
1 CRUD de perfiles [x] Create + Read + Delete + Update(apariencia/clonar/reset). Completo.
2 CRUD de ventanas [ ] No hay nada. Falta crear/listar/mover/redimensionar/cerrar ventanas (Browser.*WindowBounds).
3 CRUD de pestañas [x] Create/List/Navigate + close/activate (cdp_close_tab/activate_tab) + back/forward. Completo.
4 Lanzador personalizado [x] Perfil, flags, extensiones, proxy, headless. Completo.
5 Configuración de detalles [~] Apariencia + flag CDP global + policy de extensiones. Falta config genérica de prefs.
6 Datos del navegador (cookies, historial, marcadores) [~] Cookies: CRUD completo (get/set/delete/clear). Historial perfil: nada. Marcadores: backup/restore.
7 Lectura de página (HTML, AX tree, texto) [~] HTML sí, AX tree sí. Texto plano solo vía cdp_evaluate (no dedicado).
8 Selección de elementos del DOM [x] find_by_text, wait_element, picker interactivo, querySelector vía evaluate.
9 CRUD de iframes [x] list_frames + eval_in_frame + get_frame_html. Manejo de frames completo.
10 Lanzamiento de JS en la página [x] cdp_evaluate + steps js de cdp_extract_recipe. Completo.

Extras que ya tenemos y no estaban en la lista (capital acumulado): captura de tráfico (HAR + mitmproxy), interacción humanizada (curva Bézier + jitter anti-bot), esperas inteligentes (idle/load/element), screenshot.


Catálogo completo — todas nuestras habilidades de un vistazo

39 funciones del dominio browser (23 Go + 12 Bash + 4 pipelines Python) + 1 pipeline Bash de reset. Cada una es una tool candidata del futuro browser_mcp. Columna "MCP tool" = nombre propuesto de la tool.

CDP core — Go (functions/browser/, importables directo por el MCP)

Función (registry id) Qué hace MCP tool propuesta
chrome_launch_go_browser Lanza Chrome/Chromium con remote debugging, mata árbol de proceso browser_launch
cdp_connect_go_browser Handshake WebSocket CDP sobre localhost:port → conexión lista (interno, lo usa el MCP)
cdp_close_go_browser Cierra conexión WS y/o mata proceso Chrome por PID browser_close
cdp_navigate_go_browser Navega la pestaña a una URL (Page.navigate) tab_navigate
cdp_new_tab_go_browser Abre pestaña nueva (/json/new) → CdpTab tab_new
cdp_list_tabs_go_browser Lista pestañas/targets (GET /json), sólo HTTP tab_list
cdp_get_html_go_browser HTML del DOM vivo post-JS (outerHTML) page_get_html
cdp_screenshot_go_browser Screenshot PNG/JPEG, viewport o página completa page_screenshot
cdp_evaluate_go_browser Ejecuta JS arbitrario (Runtime.evaluate, soporta await) page_eval_js
cdp_click_go_browser Click por selector CSS (scroll + mousedown/up) dom_click
cdp_click_human_go_browser Click humanizado (Bézier + jitter + micro-pausa) anti-bot dom_click_human
cdp_click_text_go_browser Click sobre el elemento cuyo innerText matchea dom_click_text
cdp_type_text_go_browser Escribe texto char a char en el elemento activo dom_type
cdp_move_mouse_human_go_browser Mueve ratón con curva Bézier humanizada mouse_move_human
cdp_find_by_text_go_browser Texto visible → selector CSS único dom_find_by_text
cdp_wait_element_go_browser Espera a que un selector exista en el DOM dom_wait_element
cdp_pick_element_js_go_browser Picker interactivo: hover overlay + click captura selector/XPath/bbox dom_pick_element
cdp_wait_load_go_browser Espera document.readyState === complete page_wait_load
cdp_wait_idle_go_browser Espera red en idle (inflight ≤ N durante quietMs) page_wait_idle
cdp_set_cookie_go_browser Set cookie (incl. HttpOnly) vía Network.setCookie cookie_set
cdp_har_record_go_browser Captura HAR 1.2 de todo el tráfico de una acción traffic_record_har
list_chrome_profiles_go_browser Lista perfiles de un user-data-dir profile_list
list_chrome_profile_extensions_go_browser Lista extensiones instaladas de un perfil profile_list_extensions

Perfiles + sistema — Bash (bash/functions/browser/, el MCP las invoca vía fn run/shell)

Función (registry id) Qué hace MCP tool propuesta
create_chrome_profile_bash_browser Crea perfil nuevo (con/sin lanzar headless para policy) profile_create
delete_chrome_profile_bash_browser Borra perfil(es) + limpia Local State (backup automático) profile_delete
prepare_chrome_profile_bash_browser Clona user-data-dir limpio (whitelist de extensiones) profile_prepare
set_chrome_profile_appearance_bash_browser Avatar + color de tema de un perfil profile_set_appearance
backup_chrome_bookmarks_bash_browser Backup byte a byte de Bookmarks (preserva checksum) bookmark_backup
restore_chrome_bookmarks_bash_browser Restaura Bookmarks desde backup bookmark_restore
chrome_load_extensions_bash_browser Lanza Chrome con extensiones unpacked (--load-extension) ext_load_unpacked
clean_chrome_profile_extensions_bash_browser Purga extensiones fuera de la whitelist de un perfil ext_clean
apply_chromium_extension_policy_bash_browser Policy managed: forcelist + blocklist de extensiones ext_apply_policy
install_chromium_proxy_extension_bash_browser Instala extensión unpacked en todos los perfiles (persistente) ext_install_persistent
apply_chromium_cdp_flag_bash_browser Activa CDP global del sistema (/etc/chromium.d/cdp) system_cdp_flag
launch_chromium_proxy_bash_browser Lanza Chromium con perfil aislado apuntando a proxy mitm browser_launch_proxy

Pipelines — Python + Bash (*/functions/pipelines/, el MCP los invoca vía fn run)

Pipeline (registry id) Qué hace MCP tool propuesta
cdp_get_ax_tree_py_pipelines Accessibility tree completo de un tab page_get_ax_tree
cdp_open_url_and_wait_py_pipelines Crea tab + navega + espera loadEventFired → tab_id tab_open_and_wait
cdp_extract_recipe_py_pipelines Ejecuta recipe YAML (wait_selector/js) contra Chrome run_recipe
extract_hls_from_cdp_tab_py_pipelines Extrae manifests HLS de tabs + iframes extract_hls
reset_chrome_profiles_bash_pipelines Reset destructivo de perfiles (preserva bookmarks) profile_reset

El MCP tendrá ~28 tools al ensamblar lo existente, y crecerá hasta ~40 al cerrar los gaps de abajo.


Benchmark vs estado del arte (Playwright MCP + Chrome DevTools MCP)

Comparación contra los dos servidores MCP de referencia de la comunidad para fijar qué nos falta para tener paridad con un "lanzador típico":

  • Microsoft Playwright MCP — ~60+ tools (incluye testing/assertions/video). Modo por defecto = accessibility snapshot, no HTML crudo. Fuente: github.com/microsoft/playwright-mcp.
  • Google Chrome DevTools MCP — 26 tools en 6 categorías (input, navegación, emulación, performance, network, debugging), CDP crudo igual que nosotros. Fuente: github.com/ChromeDevTools/chrome-devtools-mcp.

Tabla de paridad por categoría

Categoría Ellos tienen Nosotros Veredicto
Navegación URL navigate, back/forward navigate , back/forward falta back/forward
Pestañas list/new/close/select list/new , close/activate (planeado) en gaps tanda 1
Lectura DOM snapshot (AX) + HTML AX tree , HTML paridad
Selección locators, find by text/role find_by_text , picker , wait_element paridad
Click / type click, type, press_key, hover click(+human) , type , press_key , hover falta press_key, hover
Formularios fill_form, select_option (manual con click+type) falta
Mouse xy click/move/wheel(scroll)/drag move_human , click , wheel(scroll) , drag falta scroll + drag
Diálogos handle_dialog (alert/confirm) falta (bloquea flujos)
Subida archivos file_upload falta
JS evaluate evaluate paridad
Consola console_messages falta (debug + detección)
Cookies get/list/set/delete/clear set , resto (planeado) en gaps tanda 1
Storage local localStorage/sessionStorage CRUD falta
Estado de sesión storage_state save/restore falta (login persistente)
Network captura requests list + inspect, HAR HAR , list/inspect en vivo HAR cubre; falta inspección puntual
Network mock route/abort/fulfill (intercept) (sí mitmproxy externo) falta intercept inline CDP
Network emulación online/offline, throttle falta
Emulación device emulate (device/CPU), resize viewport falta
Screenshot screenshot, PDF screenshot , PDF falta PDF
Performance trace + lighthouse falta (nicho)
Anti-bot humanizado — (ellos NO tienen) click_human, move_human, jitter ventaja nuestra
Captura tráfico proxy — (vía HAR) web_proxy mitmproxy ventaja nuestra
Perfiles (CRUD disco) — (ellos NO gestionan perfiles) create/delete/prepare/appearance/reset ventaja nuestra

Conclusión: en lectura/selección/JS/click hay paridad. Nuestras ventajas: humanización anti-bot, captura mitmproxy y gestión de perfiles en disco (Playwright/CDP-MCP no hacen nada de esto). Nos faltan, además de los gaps de la lista 1 (tabs/iframes/cookies/ventanas/historial), las capacidades de abajo (tanda 2) para alcanzar paridad de automatización.


Pendiente (gaps a construir)

CERRADOS en la tanda mínima viable (06/06/2026): #2 (tabs close/activate), #3 (cookies get/delete/clear), #6 (iframes) + tanda 2 #10 (press_key), #11 (handle_dialog), #13 (storage_state), #14 (scroll), #15 (nav back/forward). Ver sección Hecho. Lo de abajo es lo que QUEDA.

  • 1. CRUD de ventanas — funciones nuevas dominio browser: - cdp_list_windowsBrowser.getWindowForTarget por cada target → id de ventana + bounds. - cdp_set_window_bounds — mover/redimensionar/maximizar/minimizar (Browser.setWindowBounds). - cdp_new_window — abrir ventana nueva (Target con newWindow:true) vs pestaña. - cdp_close_window — cerrar una ventana concreta sin matar todo el proceso.
  • 2. Cerrar/activar pestaña individual — hoy cdp_close mata el proceso entero o cierra la conexión: - cdp_close_tabTarget.closeTarget(targetId) (cierra UNA pestaña). - cdp_activate_tabTarget.activateTarget / /json/activate/<id> (traer al frente).
  • 3. Cookies completas — hoy solo cdp_set_cookie: - cdp_get_cookiesNetwork.getCookies / getAllCookies (leer, filtrar por dominio). - cdp_delete_cookiesNetwork.deleteCookies. - cdp_clear_cookiesNetwork.clearBrowserCookies (wipe completo).
  • 4. Historial del navegador — no existe nada: - cdp_get_history — leer historial (vía History DB del perfil o Page.getNavigationHistory para la sesión actual). - cdp_clear_history — limpiar historial del perfil (decidir: SQLite del perfil con Chromium cerrado, como bookmarks).
  • 5. Marcadores CRUD individual — hoy solo backup/restore byte a byte: - cdp_add_bookmark / cdp_remove_bookmark / cdp_list_bookmarks — editar el archivo Bookmarks (JSON) preservando el checksum, o vía CDP si hay endpoint. Complementa, no sustituye, backup/restore.
  • 6. CRUD de iframes — solo hay lectura indirecta en extract_hls_from_cdp_tab: - cdp_list_frames — árbol de frames (Page.getFrameTree): id, url, parent. - cdp_eval_in_frame — ejecutar JS en el contexto de ejecución de un iframe concreto (Runtime.evaluate con el executionContextId/uniqueContextId del frame). - cdp_get_frame_html — HTML de un iframe específico. - (opcional) cdp_navigate_frame — navegar un iframe a otra URL.
  • 7. Texto plano de página dedicado — hoy se saca con cdp_evaluate("document.body.innerText"): - cdp_get_text — función dedicada que devuelve el texto visible limpio (útil para LLM/scraping rápido). Decidir si vale la pena o si el patrón vía evaluate es suficiente (no inflar por inflar).
  • 8. Configuración de detalles genérica — hoy solo apariencia + flag CDP + policy extensiones: - Evaluar si hace falta set_chrome_profile_pref (editar Preferences del perfil: idioma, descargas, permisos por defecto, etc.) o si se cubre caso por caso. NO construir hasta tener caso real.
  • 9. Playground del proyectoweb_scraping no tiene playground/ (sí lo tienen analysis/nats y message_bus/unibus). Candidato: un playground/ con UI mínima (server single-file) que liste las capacidades CDP y deje lanzarlas contra una pestaña viva para probarlas visualmente. Opcional, solo si aporta para validar las funciones nuevas.

Tanda 2 — gaps detectados en el benchmark (paridad con Playwright/CDP-MCP)

Prioridad ALTA (bloquean automatización real, los construiría antes que ventanas/historial):

  • 10. cdp_press_key HECHO — Input.dispatchKeyEvent con tabla de teclas especiales.
  • 11. cdp_handle_dialog HECHO — auto-handler Page.javascriptDialogOpening (con go sendCDP anti-deadlock).
  • 12. cdp_get_console — capturar mensajes de consola y excepciones JS (Runtime.consoleAPICalled + Runtime.exceptionThrown). Debug + detección de errores de la página. PENDIENTE — único ALTA de tanda 2 sin construir. Sube a P1 (ver análisis LLM-readiness).
  • 13. cdp_save_storage_state / cdp_load_storage_state HECHO — cookies + localStorage a archivo. ⚠️ Falta sessionStorage y forzar navigate-first (ver deuda P2 del análisis).
  • 14. cdp_scroll HECHO — Input.dispatchMouseEvent mouseWheel. ⚠️ punto (100,100) hardcodeado (deuda P1).
  • 15. cdp_nav_back / cdp_nav_forward HECHO — Page.getNavigationHistory + navigateToHistoryEntry.

Prioridad MEDIA (formularios, storage fino, subida, intercept):

  • 16. cdp_select_option — seleccionar valor en <select> (vía cdp_evaluate envuelto o CDP).
  • 17. cdp_hover — hover sobre elemento (Input.dispatchMouseEvent mouseMoved) para menús desplegables que aparecen al pasar el ratón.
  • 18. cdp_file_upload — adjuntar archivos a un <input type=file> (DOM.setFileInputFiles).
  • 19. cdp_storage_get / set / clear — CRUD de localStorage y sessionStorage (vía evaluate o DOMStorage domain). Útil si no se quiere todo el storage_state.
  • 20. cdp_intercept_requests — interceptar/abortar/modificar/mockear peticiones inline vía Fetch.enable (bloquear ads/trackers, mockear respuestas, inyectar headers). Complementa, no sustituye, al web_proxy mitmproxy (este es inline sin proxy externo).
  • 21. cdp_emulate_network — online/offline + throttle (Network.emulateNetworkConditions).
  • 22. cdp_save_pdf — guardar la página como PDF (Page.printToPDF).

Prioridad BAJA (formularios compuestos, emulación device, performance, drag):

  • 23. cdp_fill_form — rellenar varios campos de una (composición de find+click+type, candidato a pipeline no a función — encaja con la doctrina de promover composiciones).
  • 24. cdp_emulate_device — viewport/userAgent/touch móvil (Emulation.setDeviceMetricsOverride).
  • 25. cdp_drag_drop — drag and drop entre elementos.
  • 26. Performance/Lighthousecdp_perf_trace (Tracing domain) + audit Lighthouse. Nicho, solo si aparece caso de análisis de rendimiento web.

En curso

  • [~] (ninguna ahora mismo — documento recién creado)

Hecho (lo que YA tenemos)

  • Gap #1 — bucle percibir→actuar por #ref + auto-observe (06/06/2026, 9/9 e2e) - #ref = backendDOMNodeId (estable, no el efímero del AX) → ref→acción + refs estables resueltos juntos y stateless (sin mapa en el MCP). Validado con dump de AXNode real antes de codear. - Funciones nuevas: cdp_click_xy_human (primitivo de click humanizado por coords, compartido por selector/#ref/visión), cdp_click_ref, cdp_type_ref, cdp_hover_ref. cdp_click_human refactorizado para usar el primitivo (un solo camino de click). - MCP: tools dom_click_ref/dom_type_ref/dom_hover_ref con auto-observe (devuelven el outline tras la acción). browser_mcp v0.3.0, 39 tools. - render_ax_outline mejorado (defectos F1): guard de ciclo + profundidad, sin ljust, renderiza value. - Validado prueba e2e 9: login en the-internet solo por #ref, sin un selector CSS. - Pendiente de la familia: política de humanización por sesión (human/fast/instant). - enlace: functions/browser/cdp_{click_xy_human,click_ref,type_ref,hover_ref}.go + render_ax_outline.py
  • Tanda de deuda A+D+E+B — 4 fixes + 8/8 e2e (06/06/2026) - A aislamiento robusto: chrome_launch usa el binario real (salta el wrapper que pisaba flags). - D sessionStorage añadido a storage_state (save+load). Validado por prueba e2e 6. - E cdp_find_by_text devuelve error en no-encontrado (antes vacío silencioso). Validado por prueba 7. - B fin del fire-and-forget: cdp_click verifica visibilidad, cdp_type_text verifica foco. Validado por prueba 8. - La batería e2e pasó de 5 a 8 pruebas, todas verdes. Pendiente: C (Enter en widgets JS), cdp_scroll con target (P1.5), puente percepción→acción por nodeId (P1.3). - enlace: functions/browser/{chrome_launch,cdp_save_storage_state,cdp_load_storage_state,cdp_find_by_text,cdp_click,cdp_type_text}.go
  • Fase C — validación e2e real: 5/5 PASS (06/06/2026, headless + ventana visible) - resultado: batería projects/web_scraping/demo_e2e/ contra sitios sandbox (quotes/books.toscrape.com, the-internet.herokuapp.com). 5 tareas simples→complejas: extracción estructurada, percepción AX, teclado/form, login persistente (storage_state), scraping paginado+dedup. Cliente MCP stdio secuencial. Chrome aislado en 9333. - 3 bugs reales encontrados y arreglados ejecutando (lo que "compila" no detecta): page_perceive (args posicionales a fn run), cdp_save_storage_state (filtrar cookies por dominio), cdp_load_storage_state (añadir url por cookie para httpOnly). Login persistente ahora funciona. - enlace: projects/web_scraping/demo_e2e/RESUMEN.md + results/
  • browser_mcp v1 — servidor MCP de control de navegador (Go, 06/06/2026) - resultado: app en projects/web_scraping/apps/browser_mcp/ (sub-repo Gitea, git init hecho). 36 tools (v0.2.0), pool de conexiones por puerto, stdio + --http + --read-only. Build verde (smoke tools/list=36). Registrado en projects/web_scraping/.mcp.json como server browser. - Fase B.5 (P0 LLM-readiness) cerrada: Chrome aislado 9333, tab_select determinista, page_get_text, page_perceive. Pendiente Fase C (e2e real contra Chrome) + P1 (verificación post-acción). - enlace: projects/web_scraping/apps/browser_mcp/ — patrón apps/registry_mcp.
  • Fix bug %v en cdp_evaluate + cdp_eval_in_frame (06/06/2026) - resultado: objetos/arrays JS ahora se serializan con json.Marshal (antes repr de Go inservible). Build+vet+test del paquete browser verdes. Reindexado. - enlace: functions/browser/cdp_evaluate.go, cdp_eval_in_frame.go
  • Tanda mínima viable del MCP — 15 funciones CDP nuevas (Go, dominio browser, 06/06/2026) - resultado: 5 fn-constructor en paralelo. Compila (go build/vet/test verdes), indexado (fn index), 15 entradas confirmadas. Tag de grupo navegator en todas. - Tabs/navegación: cdp_close_tab_go_browser, cdp_activate_tab_go_browser (registradas — el código ya vivía en cdp_list_tabs.go), cdp_nav_back_go_browser, cdp_nav_forward_go_browser. - Iframes: cdp_list_frames_go_browser, cdp_eval_in_frame_go_browser, cdp_get_frame_html_go_browser. - Cookies: cdp_get_cookies_go_browser, cdp_delete_cookies_go_browser, cdp_clear_cookies_go_browser. - Input/diálogos: cdp_press_key_go_browser, cdp_scroll_go_browser, cdp_handle_dialog_go_browser. - Sesión: cdp_save_storage_state_go_browser, cdp_load_storage_state_go_browser (login persistente). - enlace: functions/browser/cdp_*.go — cierra gaps #2, #3, #6(cookies), #9 + tanda2 #10/#11/#13/#14/#15.
  • Perfiles — CRUD completo (Bash, dominio browser) - resultado: Create create_chrome_profile, Read list_chrome_profiles (+ list_chrome_profile_extensions), Delete delete_chrome_profile, Update set_chrome_profile_appearance (avatar + color de tema) / prepare_chrome_profile (clonar limpio) / reset_chrome_profiles (pipeline reset destructivo con preservación de bookmarks). - enlace: bash/functions/browser/, bash/functions/pipelines/reset_chrome_profiles.md
  • Lanzador personalizado (Go + Bash) - resultado: chrome_launch (remote debugging, multi-OS, mata árbol de proceso), launch_chromium_proxy (perfil aislado apuntando a proxy mitm/Burp), chrome_load_extensions (unpacked), apply_chromium_cdp_flag (CDP global del sistema), apply_chromium_extension_policy + install_chromium_proxy_extension (distribuir extensiones), y subcomando launch de script_navegador. - enlace: functions/browser/chrome_launch.go, bash/functions/browser/
  • Pestañas — crear / listar / navegar - resultado: cdp_new_tab, cdp_open_url_and_wait (crear+navegar+esperar load), cdp_list_tabs, cdp_navigate. (Falta cerrar/activar una pestaña concreta → Pendiente #2.) - enlace: functions/browser/cdp_new_tab.md, cdp_list_tabs.go, cdp_navigate.go
  • Lectura de página — HTML + Accessibility tree - resultado: cdp_get_html (DOM vivo post-JS), cdp_get_ax_tree (pipeline Python, AX tree completo). Texto plano hoy vía cdp_evaluate (ver Pendiente #7). - enlace: functions/browser/cdp_get_html.go, python/functions/pipelines/cdp_get_ax_tree.md
  • Selección de elementos del DOM - resultado: cdp_find_by_text (texto→selector CSS único), cdp_wait_element (polling existencia), cdp_pick_element_js (picker interactivo: hover overlay + click captura selector/XPath/bbox), querySelector arbitrario vía cdp_evaluate. - enlace: functions/browser/cdp_find_by_text.go, cdp_pick_element_js.js, cdp_wait_element.go
  • Lanzamiento de JS en la página - resultado: cdp_evaluate (expresión JS arbitraria, soporta await, reporta excepciones), steps js de cdp_extract_recipe (recipe YAML). - enlace: functions/browser/cdp_evaluate.go, python/functions/pipelines/cdp_extract_recipe.md
  • Marcadores — backup / restore - resultado: backup_chrome_bookmarks + restore_chrome_bookmarks (copia byte a byte preservando checksum, sin reserializar JSON). CRUD individual de bookmarks pendiente (#5). - enlace: bash/functions/browser/backup_chrome_bookmarks.sh, restore_chrome_bookmarks.sh
  • Cookies — set - resultado: cdp_set_cookie (incl. HttpOnly, para auth e2e). get/delete/clear pendientes (#3). - enlace: functions/browser/cdp_set_cookie.go
  • Extras (capital acumulado, fuera de la lista pedida) - resultado: captura de tráfico cdp_har_record (HAR 1.2) + app web_proxy (mitmproxy siempre activo); interacción humanizada cdp_click_human / cdp_move_mouse_human / cdp_type_text (anti-detección); esperas inteligentes cdp_wait_idle / cdp_wait_load / cdp_wait_element; cdp_screenshot; pipeline extract_hls_from_cdp_tab (manifests HLS de tabs+iframes). - enlace: functions/browser/, projects/web_scraping/apps/web_proxy

MCP full-CDP (browser_mcp) — estado e iteración

Meta: un servidor MCP que da a cualquier agente Claude control total del navegador vía CDP. Nombre resuelto: browser_mcp (genérico, para todo control de navegador, no solo CDP).

Estado actual — v1 construido (06/06/2026)

  • App: projects/web_scraping/apps/browser_mcp/ (Go, sub-repo Gitea propio, git init hecho). Patrón registry_mcp: github.com/mark3labs/mcp-go v0.52.0, archivos tools_<grupo>.go, registro en main.go, stdio por defecto + --http opcional + flag --read-only. Build verde, 33 tools.
  • Pool de conexiones (resuelto: pool por puerto, NO connect-per-tool). Ver explicación abajo.
  • Registro: projects/web_scraping/.mcp.json con el server browser.
  • Omitido v1: cdp_har_record (requiere callback), cdp_get_ax_tree (pipeline Python), perfiles Bash (requieren Chrome cerrado → incompatible con un Chrome vivo).

Pool de conexiones — por qué es requisito, no opción

browser.CdpConnect(port) hace un handshake WebSocket a una tab "page" de Chrome (~50-200 ms) y esa conexión ES una sesión viva (Page./Runtime./Input.* + un readLoop en goroutine + event handlers). Si reconectáramos en cada tool: (1) pagaríamos el handshake cada vez, (2) perderíamos estado entre tools — los handlers de eventos (p.ej. el auto-handler de handle_dialog) mueren al cerrar la conexión. Por eso browser_mcp mantiene map[port]→*CDPConn: la primera tool que toca el puerto abre la conexión, las siguientes la reusan; se cierra al apagar el MCP o con browser_disconnect. Sin pool, encadenar navigate→wait→click→eval es imposible (cada fn run suelto pierde la conexión al terminar el proceso).

⚠️ Deuda crítica (análisis LLM-readiness) — ver sección dedicada abajo

El v1 envuelve las funciones tal cual. Un LLM percibe-decide-actúa-verifica; las funciones están hechas para un script que ya sabe qué hacer. Antes de declarar el MCP "usable por un agente" hay que cerrar los P0 de la sección siguiente (percepción compacta + verificación + target determinista). El valor del MCP está en lo que AÑADE encima, no en el wrapping.

Fases

  • Fase 0 — inventario + catálogo + plan.
  • Fase A — 15 funciones gap de la tanda mínima viable. (5 fn-constructor paralelos)
  • Fase B — ensamblar browser_mcp v1 (33 tools, pool, build verde).
  • Fase B.5 — NUEVO, BLOQUEANTE — cerrar los P0 del análisis (abajo) y elevar el MCP de "wrapper" a "capa de agente": percepción compacta, verificación post-acción, target determinista.
  • Fase C — registrar en Claude + e2e (un agente abre Chrome aislado, navega, lee, click, extrae) + documentar en LLM_BROWSER_GUIDE.md.

Capability group

Crear/actualizar docs/capabilities/browser.md con el cluster completo (39 funciones + 15 nuevas) + ejemplo canónico end-to-end + las tools del MCP, para cargar el grupo en un solo read.


Análisis LLM-readiness — deuda P0/P1/P2

Crítica recibida (06/06/2026): el núcleo CDP es sólido y la cobertura de verbos casi completa, pero el sistema está hecho para un programa que ya sabe qué hacer, no para un LLM que percibe-decide-actúa-verifica. Faltan las dos piezas que un agente necesita: percibir sin colapsar el contexto y saber si la acción funcionó. Evaluado contra el bucle PERCIBIR → DECIDIR → ACTUAR → VERIFICAR (+ ESTADO transversal).

Ya corregido este turno

  • BUG GRAVE cdp_evaluate / cdp_eval_in_frame — usaban fmt.Sprintf("%v", value); objetos/arrays JS llegaban como repr de Go (map[a:1]) en vez de JSON. Arreglado: json.Marshal para no-strings. (Sin esto el scraping de datos estructurados era inservible.)
  • Comentario mentiroso de cdp_navigate — decía "espera Page.loadEventFired"; el código solo lanza Page.navigate. Comentario corregido: NO espera carga, hay que encadenar CdpWaitLoad/CdpWaitIdle.

P0 — CERRADOS (06/06/2026, Fase B.5)

  • P0.1 render_ax_outline render_ax_outline_py_core (puro: nodos AX → outline indentado con #ref) + pipeline cdp_perceive_outline_py_pipelines (compone cdp_get_ax_tree + trim_ax_tree + render_ax_outline). Expuesto como tool page_perceive del MCP (vía fn run). La pieza de PERCEPCIÓN.
  • P0.2 Lecturas con límite cdp_get_text_go_browser (texto visible, selector opcional, maxBytes con corte rune-safe). Tool page_get_text del MCP (default 20000 bytes). get_html se deja intacto (sin romper firma); el truncado de HTML vive en la tool del MCP (200k). Decisión KISS documentada.
  • P0.3 Target determinista + Chrome aislado cdp_connect_target_go_browser (elige target por id o substring de URL) + refactor cdp_connect.go (helper cdpConnectWS). En el MCP: default puerto 9333 = Chrome aislado del MCP (no el 9222 diario), browser_launch con user_data_dir dedicado, y tool tab_select para fijar la pestaña determinísticamente. Cierra el riesgo de operar sobre banca/correo. - [x] Aislamiento robusto del binario (06/06) — chrome_launch usa el binario real /usr/lib/chromium/chromium (salta el wrapper /etc/chromium.d/cdp que inyectaba flags globales). Antes el aislamiento dependía del orden de los flags.

P1 — fiabilidad de acción

  • P1.1 Verificación post-acción (06/06) — cdp_click verifica visibilidad (oculto → error, no clic en (0,0)); cdp_type_text verifica foco editable (sin foco → error). Validado por prueba e2e 8. PENDIENTE: cdp_scroll/press_key con confirmación de efecto (menor).
  • P1.2 cdp_find_by_text honesto (06/06) — ahora devuelve error explícito en no-encontrado (antes ("", nil) silencioso). Validado por prueba e2e 7. (Aviso de múltiples matches: pendiente, menor.)
  • P1.3 Puente percepción→acción — el LLM percibe en AX tree (role/name/nodeId) pero actúa por selector CSS. Falta click(nodeId)/act(#ref) para actuar por ref del snapshot (como Playwright), sin adivinar CSS.
  • P1.4 cdp_type_text verifica focus (06/06) — error claro si no hay campo editable enfocado (antes el texto iba a document.body en silencio). Validado por prueba e2e 8.
  • P1.5 cdp_scroll con target — punto (100,100) hardcodeado; si ahí hay un navbar fixed no scrollea el contenido. Permitir x,y o selector/elemento objetivo.
  • P1.6 cdp_get_console (era tanda2 #12) — capturar consola + excepciones; el LLM detecta errores de página.

P2 — paridad

  • P2.1 cdp_select_option, cdp_file_upload, cdp_hover (ver tanda 2 #16-18).
  • P2.2 storage_state (06/06) — cookies (filtradas por dominio) + localStorage + sessionStorage + login persistente, todo validado e2e (pruebas 4 y 6). load sigue exigiendo navigate-first al dominio (documentado).

Implicación: el MCP NO es "envolver 39 funciones". Es la capa que arregla los 4 ejes (pool=estado, representaciones compactas=percepción, JSON real=ya hecho, verificación=acción fiable). Un MCP que solo expone las funciones hereda todos los defectos.


Roadmap MCP de clase — benchmark Playwright + Visión (apuntado 06/06/2026)

Objetivo: pasar de "wrapper con ~36 tools" a un MCP de clase. La métrica NO es el número de tools (Playwright MCP ~60, Chrome DevTools MCP 26) — gran parte de los 60 de Playwright son inflado (storage desglosado, video/tracing). Lo que sube el nivel real es cerrar los 4 gaps de clase + dar al agente tres sentidos de percepción→acción.

Los tres sentidos del agente (percepción → acción)

El agente tendrá tres vías para "ver" una página y actuar sobre ella. Cada una necesita su puente a la acción:

  1. DOM / AX tree (hoy parcial) — page_perceive → outline con #ref. Falta el puente #ref → acción.
  2. Texto (hoy) — cdp_get_text (compacto, selector opcional).
  3. Visión (futuro, el usuario aportará los modelos) — screenshot → OCR (texto + bbox) + YOLO (objetos + bbox) → el agente ve la página como imagen. Puente a la acción = coordinate mouse (click_xy sobre el bounding box detectado). Por esto coordinate mouse NO es inflado: es el sentido de la mano para el ojo visual.

Transversal — humanización SIEMPRE en las acciones (anti-detección)

REGLA DE DISEÑO: todas las acciones de ratón/teclado del agente usan por defecto la variante humanizada (curva de Bézier + jitter + micro-pausas variables), no el evento sintético directo. Ya existen cdp_click_human y cdp_move_mouse_human; el cdp_type_text ya escribe char a char con pausa. Aplicar:

  • El puente #ref → acción (A1) y click_xy (C1) deben ir por defecto por el camino humanizado (mover el ratón con Bézier hasta el destino + click con micro-pausa press/release), no por Input.dispatchMouseEvent seco. Exponer un flag instant=true solo para tests/velocidad.
  • Donde falte versión humanizada (scroll, drag_xy), crear la variante con jitter/easing.
  • Objetivo: que el tráfico de input sea indistinguible de un humano — es ventaja nuestra frente a Playwright/CDP-MCP, que no humanizan. No perderla al añadir tools nuevas.

A. Gaps de clase (los 4 que de verdad suben el nivel)

  • A1 — Puente #ref → acción (06/06). cdp_click_ref/cdp_type_ref/cdp_hover_ref + primitivo cdp_click_xy_human. Tools MCP dom_click_ref/type_ref/hover_ref. Validado prueba e2e 9. Hoy el outline da #ref=44 pero el LLM no puede usarlo: tiene que volver a selector CSS. Cierra el loop percibir↔actuar. Gap #1 ahora.
  • A2 — Refs estables (06/06). Resuelto stateless: el #ref ES el backendDOMNodeId (estable mientras el nodo viva), no el nodeId efímero del AX. Sin mapa de estado en el MCP. render_ax_outline actualizado.
  • A3 — Auto-observe tras acción (06/06). Las tools _ref del MCP devuelven el outline AX actualizado tras la acción (settle 400ms + perceiveOutline). Verificación implícita. Validado prueba 9.
  • A4 — Política de target segura en el MCP (P0 seguridad). cdp_connect_target da la herramienta; falta la regla: el MCP lanza Chrome propio (perfil + puerto dedicados, ya en 9333) o exige target explícito; nunca engancha a la tab del 9222 por match="".
  • A5 — Intercept / mock de red (Fetch.enable) (P0 programático). Mockear APIs, bloquear recursos, inyectar headers. La tool más valiosa de Playwright (route). Hoy 0.

B. Tools valiosas del benchmark Playwright (delta real, ~12)

  • B1 verbos de formulario: hover, select_option (<select>), file_upload (DOM.setFileInputFiles), drag/drop.
  • B2 network observability: network_requests (lista en vivo) + network_request (inspeccionar uno). Complementa el HAR post-mortem.
  • B3 console_messages: capturar consola + excepciones JS (Runtime.consoleAPICalled). Debug + detección.
  • B4 assertions (modo programático): verify_element_visible / verify_text_visible / verify_value. Es el EJE VERIFICAR aplicado a recetas YAML (assert por paso).

C. Coordinate mouse — IMPORTANTE (base del modo visión)

Reclasificado de "inflado" a importante por el usuario: es el puente entre visión (bbox de OCR/YOLO) y acción.

  • C1 cdp_click_xy(x, y) — click por coordenadas (sobre lo que la visión detecta).
  • C2 cdp_move_xy / cdp_mouse_down / cdp_mouse_up — control fino del ratón por píxeles.
  • C3 cdp_drag_xy(x1,y1,x2,y2) — drag por coordenadas.
  • C4 cdp_scroll ya existe; añadir target por coordenadas/elemento (P1.5).

D. Misc — IMPORTANTE

  • D1 cdp_save_pdf (Page.printToPDF) — exportar página a PDF.
  • D2 cdp_get_console (= B3) — consola + excepciones.
  • D3 cdp_resize / cdp_emulate_device (Emulation.setDeviceMetricsOverride) — viewport conocido (clave para visión: coordenadas estables) + mobile/touch.
  • D4 cdp_nav_back/forward ya existen; wait_for cubierto por wait_load/idle/element.
  • Screenshot como MCP image content (hoy page_screenshot va a archivo → el LLM no lo ve). Prerequisito del modo visión.

E. VISIÓN (OCR + YOLO) — tarea futura, el usuario aporta los modelos

  • E1 Pipeline de percepción visual: page_screenshot (a buffer) → OCR (texto + bbox) + YOLO (objetos UI + bbox) → estructura {label, text, bbox} que el agente consume como "outline visual".
  • E2 Función ocr_page y detect_ui_elements (los modelos los aportará el usuario). Dominio nuevo (¿vision?) o browser. Probable Python (modelos ML).
  • E3 Puente visión → acción vía coordinate mouse (sección C): el agente clica el centro del bbox.
  • E4 Screenshot como image content en el MCP (D) para que el LLM también vea el píxel directamente.
  • Nota: la visión es el tercer sentido — complementa, no sustituye, al AX outline (que es más barato en tokens). Útil cuando el DOM miente (canvas, iframes cross-origin, apps que pintan en <canvas>).

F. Defectos de calidad a corregir en lo ya construido (del coach)

  • F1 (06/06) render_ax_outline: guard de ciclo (visited) + límite de profundidad (_MAX_DEPTH=60); ljust(60) eliminado; renderiza el value de inputs (= 'texto'). Hecho en la misma edición del #ref.
  • F2 cdp_get_html sin límite: documentar que es "crudo a propósito" (la vía compacta es get_text + outline).
  • F3 cdp_connect_target con match="": documentar que es inseguro fuera del MCP; la política segura vive en A4.
  • F4 Limpieza de recursos: isolated worlds que crea cdp_eval_in_frame, conexiones del pool del MCP.

G. Inflado de Playwright — NO construir salvo necesidad concreta

Storage granular desglosado (cookie/localStorage/sessionStorage × get/set/delete/list/clear = 17 tools; nosotros lo hacemos con 6), video/tracing/highlight (9 tools de debug visual de testing), generate_locator, run_code_unsafe (= nuestro page_eval_js). Replicar esto sube el contador a ~45 sin añadir poder.

Telemetría

call_monitor ya existe — cada tool del MCP encaja sin trabajo extra.


Enlaces

  • App orquestadora — projects/web_scraping/apps/script_navegador (CLI rápido: open/click/type/eval/html/shot/wait/tabs/launch/close/profiles + runner YAML)
  • App captura — projects/web_scraping/apps/web_proxy (mitmproxy, service systemd-user puerto 8080)
  • Guía LLM — projects/web_scraping/LLM_BROWSER_GUIDE.md
  • Setup CDP global — projects/web_scraping/CHROMIUM_SYSTEM.md
  • Dominio browser en registry — mcp__registry__fn_search query="" domain="browser"

Issues / flows relacionados

  • (ninguno aún — al priorizar los gaps, abrir issue por bloque o delegar a fn-constructor)

Notas

  • Decisión de arquitectura: el control de navegador es CDP crudo sobre Chrome/Chromium en Linux nativo, no Playwright/Selenium. Toda capacidad reutilizable vive en functions/browser/; las apps solo orquestan.
  • Prioridad sugerida de gaps (mayor impacto scraping/automatización primero):
    1. Cerrar/activar pestaña individual (#2) y CRUD de iframes (#6) — bloquean automatización de SPAs reales.
    2. Cookies completas (#3) — leer/borrar cookies es básico para sesiones y limpieza.
    3. CRUD de ventanas (#1) — útil para multi-ventana y posicionamiento, menos urgente para scraping headless.
    4. Historial (#4) y bookmarks CRUD (#5) — nicho, construir cuando haya caso concreto.
  • No inflar por inflar: cdp_get_text (#7) y config genérica de prefs (#8) solo si aparece un caso real repetido; el patrón vía cdp_evaluate puede ser suficiente (regla function_growth_and_self_docs).
  • Cada función nueva del dominio browser debe declararse en uses_functions del app.md que la consuma (el indexer no deduce deps en Go automáticamente para apps).