- 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>
42 KiB
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:
- Inventario — mapear todas las capacidades de control de navegador del proyecto
web_scrapingcontra el dominiobrowserdel registry (funciones Go, Bash y pipelines Python) y la appscript_navegador. Marcar qué está cubierto, qué está a medias y qué falta. - 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 variosfn-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íacdp_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_windows—Browser.getWindowForTargetpor cada target → id de ventana + bounds. -cdp_set_window_bounds— mover/redimensionar/maximizar/minimizar (Browser.setWindowBounds). -cdp_new_window— abrir ventana nueva (Target connewWindow:true) vs pestaña. -cdp_close_window— cerrar una ventana concreta sin matar todo el proceso. - 2. Cerrar/activar pestaña individual — hoy
cdp_closemata el proceso entero o cierra la conexión: -cdp_close_tab—Target.closeTarget(targetId)(cierra UNA pestaña). -cdp_activate_tab—Target.activateTarget//json/activate/<id>(traer al frente). - 3. Cookies completas — hoy solo
cdp_set_cookie: -cdp_get_cookies—Network.getCookies/getAllCookies(leer, filtrar por dominio). -cdp_delete_cookies—Network.deleteCookies. -cdp_clear_cookies—Network.clearBrowserCookies(wipe completo). - 4. Historial del navegador — no existe nada:
-
cdp_get_history— leer historial (víaHistoryDB del perfil oPage.getNavigationHistorypara 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 archivoBookmarks(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.evaluatecon elexecutionContextId/uniqueContextIddel 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(editarPreferencesdel perfil: idioma, descargas, permisos por defecto, etc.) o si se cubre caso por caso. NO construir hasta tener caso real. - 9. Playground del proyecto —
web_scrapingno tieneplayground/(sí lo tienenanalysis/natsymessage_bus/unibus). Candidato: unplayground/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.dispatchKeyEventcon tabla de teclas especiales. - 11.
cdp_handle_dialog✅ HECHO — auto-handlerPage.javascriptDialogOpening(congo sendCDPanti-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. ⚠️ FaltasessionStoragey 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íacdp_evaluateenvuelto 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 oDOMStoragedomain). Útil si no se quiere todo el storage_state. - 20.
cdp_intercept_requests— interceptar/abortar/modificar/mockear peticiones inline víaFetch.enable(bloquear ads/trackers, mockear respuestas, inyectar headers). Complementa, no sustituye, alweb_proxymitmproxy (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/Lighthouse —
cdp_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_humanrefactorizado para usar el primitivo (un solo camino de click). - MCP: toolsdom_click_ref/dom_type_ref/dom_hover_refcon auto-observe (devuelven el outline tras la acción). browser_mcp v0.3.0, 39 tools. -render_ax_outlinemejorado (defectos F1): guard de ciclo + profundidad, sinljust, renderizavalue. - 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_launchusa el binario real (salta el wrapper que pisaba flags). - DsessionStorageañadido astorage_state(save+load). Validado por prueba e2e 6. - Ecdp_find_by_textdevuelve error en no-encontrado (antes vacío silencioso). Validado por prueba 7. - B fin del fire-and-forget:cdp_clickverifica visibilidad,cdp_type_textverifica foco. Validado por prueba 8. - La batería e2e pasó de 5 a 8 pruebas, todas verdes. Pendiente: C (Enter en widgets JS),cdp_scrollcon 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ñadirurlpor cookie para httpOnly). Login persistente ahora funciona. - enlace: projects/web_scraping/demo_e2e/RESUMEN.md + results/ browser_mcpv1 — servidor MCP de control de navegador (Go, 06/06/2026) - resultado: app enprojects/web_scraping/apps/browser_mcp/(sub-repo Gitea,git inithecho). 36 tools (v0.2.0), pool de conexiones por puerto, stdio +--http+--read-only. Build verde (smoketools/list=36). Registrado enprojects/web_scraping/.mcp.jsoncomo serverbrowser. - ✅ Fase B.5 (P0 LLM-readiness) cerrada: Chrome aislado 9333,tab_selectdeterminista,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ónapps/registry_mcp.- Fix bug
%vencdp_evaluate+cdp_eval_in_frame(06/06/2026) - resultado: objetos/arrays JS ahora se serializan conjson.Marshal(antes repr de Go inservible). Build+vet+test del paquetebrowserverdes. 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: 5fn-constructoren paralelo. Compila (go build/vet/testverdes), indexado (fn index), 15 entradas confirmadas. Tag de gruponavegatoren todas. - Tabs/navegación:cdp_close_tab_go_browser,cdp_activate_tab_go_browser(registradas — el código ya vivía encdp_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: Createcreate_chrome_profile, Readlist_chrome_profiles(+list_chrome_profile_extensions), Deletedelete_chrome_profile, Updateset_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 subcomandolaunchdescript_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íacdp_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íacdp_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), stepsjsdecdp_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) + appweb_proxy(mitmproxy siempre activo); interacción humanizadacdp_click_human/cdp_move_mouse_human/cdp_type_text(anti-detección); esperas inteligentescdp_wait_idle/cdp_wait_load/cdp_wait_element;cdp_screenshot; pipelineextract_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 inithecho). Patrónregistry_mcp:github.com/mark3labs/mcp-gov0.52.0, archivostools_<grupo>.go, registro enmain.go, stdio por defecto +--httpopcional + 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.jsoncon el serverbrowser. - 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_mcpv1 (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— usabanfmt.Sprintf("%v", value); objetos/arrays JS llegaban como repr de Go (map[a:1]) en vez de JSON. Arreglado:json.Marshalpara 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 lanzaPage.navigate. Comentario corregido: NO espera carga, hay que encadenarCdpWaitLoad/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) + pipelinecdp_perceive_outline_py_pipelines(componecdp_get_ax_tree+trim_ax_tree+render_ax_outline). Expuesto como toolpage_perceivedel MCP (víafn run). La pieza de PERCEPCIÓN. - P0.2 Lecturas con límite ✅ —
cdp_get_text_go_browser(texto visible, selector opcional,maxBytescon corte rune-safe). Toolpage_get_textdel MCP (default 20000 bytes).get_htmlse 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) + refactorcdp_connect.go(helpercdpConnectWS). En el MCP: default puerto 9333 = Chrome aislado del MCP (no el 9222 diario),browser_launchconuser_data_dirdedicado, y tooltab_selectpara fijar la pestaña determinísticamente. Cierra el riesgo de operar sobre banca/correo. - [x] Aislamiento robusto del binario ✅ (06/06) —chrome_launchusa el binario real/usr/lib/chromium/chromium(salta el wrapper/etc/chromium.d/cdpque 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_clickverifica visibilidad (oculto → error, no clic en (0,0));cdp_type_textverifica foco editable (sin foco → error). Validado por prueba e2e 8. PENDIENTE:cdp_scroll/press_keycon confirmación de efecto (menor). - P1.2
cdp_find_by_texthonesto ✅ (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_textverifica focus ✅ (06/06) — error claro si no hay campo editable enfocado (antes el texto iba adocument.bodyen silencio). Validado por prueba e2e 8. - P1.5
cdp_scrollcon 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).loadsigue 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:
- DOM / AX tree (hoy parcial) —
page_perceive→ outline con#ref. Falta el puente#ref→ acción. - Texto (hoy) —
cdp_get_text(compacto, selector opcional). - 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_xysobre 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) yclick_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 porInput.dispatchMouseEventseco. Exponer un flaginstant=truesolo 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+ primitivocdp_click_xy_human. Tools MCPdom_click_ref/type_ref/hover_ref. Validado prueba e2e 9. Hoy el outline da#ref=44pero 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
#refES elbackendDOMNodeId(estable mientras el nodo viva), no elnodeIdefímero del AX. Sin mapa de estado en el MCP.render_ax_outlineactualizado. - A3 — Auto-observe tras acción ✅ (06/06). Las tools
_refdel 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_targetda 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 pormatch="". - 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_scrollya 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/forwardya existen;wait_forcubierto por wait_load/idle/element. - Screenshot como MCP image content (hoy
page_screenshotva 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_pageydetect_ui_elements(los modelos los aportará el usuario). Dominio nuevo (¿vision?) obrowser. 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 elvaluede inputs (= 'texto'). Hecho en la misma edición del#ref. - F2
cdp_get_htmlsin límite: documentar que es "crudo a propósito" (la vía compacta es get_text + outline). - F3
cdp_connect_targetconmatch="": 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):
- Cerrar/activar pestaña individual (#2) y CRUD de iframes (#6) — bloquean automatización de SPAs reales.
- Cookies completas (#3) — leer/borrar cookies es básico para sesiones y limpieza.
- CRUD de ventanas (#1) — útil para multi-ventana y posicionamiento, menos urgente para scraping headless.
- 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íacdp_evaluatepuede ser suficiente (regla function_growth_and_self_docs). - Cada función nueva del dominio
browserdebe declararse enuses_functionsdelapp.mdque la consuma (el indexer no deduce deps en Go automáticamente para apps).