En esta página
CrawlForge MCP Server v5.0.0 ya está disponible. Es la versión más grande que hemos publicado nunca, y casi nada de ella son funciones nuevas.
En su lugar, v5.0.0 agrupa un programa de remediación de siete fases impulsado por una auditoría interna completa del código: todos los agujeros SSRF, todas las herramientas que devolvían salidas silenciosamente incorrectas, todos los temporizadores y contextos de navegador que se filtraban, el transporte HTTP que solo admitía una sesión, todas las dependencias abandonadas y las funciones de la especificación MCP que aún no habíamos adoptado. La suite de tests unitarios pasó de 480 a 914 tests. npm audit pasó de 16 vulnerabilidades a 0.
Hay exactamente un cambio incompatible: el mínimo de Node pasó de >=18.0.0 a >=20.16.0. Si estás en Node 20 o superior, actualizar es una sola línea.
Tabla de contenidos
- Qué incluye v5.0.0
- El único cambio incompatible: Node 20
- Fase 1: los agujeros de seguridad que cerramos
- Fase 2: 52 formas en que las herramientas fallaban en silencio
- Fase 3: seguro para ejecutarse durante días
- Fase 4: el despliegue remoto y HTTP ya funciona
- Fase 5: cero vulnerabilidades en npm audit
- Fase 6: adopción de la especificación MCP
- Novedades desde v4.8.0: serp_rank y guiado de herramientas
- Precios: 27 herramientas medidas, sin cambios
- Cómo actualizar
- Qué viene a continuación
Qué incluye v5.0.0
| Fase | Tema | Resultado principal |
|---|---|---|
| 0 | Actualización de dependencias | npm audit 16 vulnerabilidades → 4 moderadas, sin tocar código |
| 1 | Seguridad crítica | Bypass de literal IP en SSRF, emisión de tokens OAuth, fuga de secretos, facturación |
| 2 | Corrección | 52 arreglos — incluida una reescritura de crawl_deep que hace que los crawls reales funcionen otra vez |
| 3 | Fugas y timeouts | 24 arreglos — contextos de navegador, cachés sin límite, plazos en cada lectura de cuerpo |
| 4 | Transporte HTTP | 19 arreglos — HTTP streamable multisesión, prompts funcionales, HMAC de webhooks |
| 5 | Modernización de dependencias | Mínimo Node ≥ 20, 0 vulnerabilidades en npm audit |
| 6 | Adopción de la especificación MCP | Salida estructurada, tareas asíncronas, filtrado de herramientas, server.json del registro |
Cobertura de tests a lo largo del programa: 480 → 914 tests unitarios, con la conformidad del protocolo MCP manteniéndose en 100.0% COMPLIANT, 0 errores en cada control de fase.
El único cambio incompatible: Node 20
engines.node pasó de >=18.0.0 a >=20.16.0.
Node 18 llegó a su fin de vida en abril de 2025, y 20.16 es el mínimo que exige pdf-parse 2.4.5 — la reescritura ESM mantenida que necesitábamos para cerrar los últimos hallazgos de la auditoría. Nuestro Dockerfile (node:20-alpine) y CI (Node 22) ya lo cumplían, así que ahí no cambió nada. Si sigues en Node 18, ahora verás un aviso de engines al instalar.
Esa es toda la superficie incompatible. Ningún esquema de herramienta, forma de salida ni coste en credits cambia para quienes ya las usan.
Fase 1: los agujeros de seguridad que cerramos
Esta es la fase que conviene leer con atención si ejecutas CrawlForge cerca de una red privada.
El bypass de literal IP en SSRF era el crítico. Nuestra protección resolvía los nombres de host y comprobaba las direcciones resultantes, pero nunca aplicaba esa misma comprobación a las URLs cuyo host ya era un literal IP. http://127.0.0.1/, la forma decimal 2130706433, la forma hexadecimal 0x7f000001: el analizador de URLs de WHATWG normaliza todas ellas, y Node nunca enruta los literales IP a través de lookup, así que pasaban de largo. v5.0.0 ejecuta ipBlocked() sobre los nombres de host que son literales IP en la comprobación previa y envuelve el buildConnector del dispatcher de undici con una comprobación por conexión, de modo que un salto de redirección directo a una dirección interna también queda bloqueado.
Junto a él llegaron tres arreglos más de la protección:
- Reconocimiento de IPv6 con IPv4 mapeada.
::ffff:127.0.0.1y::ffff:169.254.169.254ahora se normalizan a su IPv4 incrustada antes de comprobar los rangos, tanto en el modo por defecto como enSSRF_STRICT. Esto elimina el bypass mediante registros AAAA controlados por DNS. BLOCKED_DOMAINSya no es configuración muerta.config.security.ssrfProtection.blockedDomainsestaba declarado y no lo leía nadie. Ahora se aplica en la comprobación previa.- La lista de permitidos se evalúa por salto. Antes, un primer salto permitido dejaba sin protección todos los saltos siguientes.
También conectamos la protección a cinco rutas que nunca la tuvieron: scrape_with_actions (con una recomprobación de page.url() posterior a la navegación que cierra la página si una redirección aterriza en un rango bloqueado, cerrando la primitiva de lectura de red interna de Playwright), map_site, las descargas de PDF de process_document, la entrega y las comprobaciones de salud de webhooks, y las notificaciones de webhook de deep_research.
Más allá del SSRF:
- OAuth.
/oauth/authorizeahora exige demostrar la API key del operador antes de emitir un código, con comparación de digest en tiempo constante. Queda cerrado el flujo anónimo de registro → autorización → token que acuñaba tokens bearer facturados al operador. - Fuga de secretos. La telemetría de uso ahora pasa los parámetros de herramienta por
maskSecrets()antes de que la carga útil salga del proceso: las API keys de terceros, las cabeceras de autenticación y los secretos de firma de webhooks ya no viajan en texto plano.deep_researchdejó de registrar las API keys de LLM en los logs de archivo de Winston. - Facturación. Un error lanzado por la propia comprobación de credits ahora factura cero: el cargo a medias de la ruta de error solo se aplica una vez que el handler ha arrancado de verdad.
checkCreditsdistingue 401/403 (key inválida o revocada) de 5xx (ventana de gracia) en lugar de reportar ambos como "credits insuficientes".
Fase 2: 52 formas en que las herramientas fallaban en silencio
La fase 2 aborda la categoría de "pasaba los smoke tests mientras devolvía salidas engañosas". Lo principal:
crawl_deep vuelve a servir para crawls reales. Las páginas hijas del BFS se esperaban desde dentro de un hueco de cola ya ocupado, lo que significaba que el timeout de la cola por tarea limitaba todo el crawl recursivo en lugar de una sola página. Cualquier crawl que superara los 30 segundos de CRAWL_TIMEOUT descartaba todas las páginas ya descargadas con un escueto Promise timed out, y las configuraciones de baja concurrencia (incluida concurrency: 1) se bloqueaban por completo. Ambos casos están arreglados.
Una muestra representativa del resto:
- Claves de caché que contradecían la petición. La clave de caché de resultados de
crawl_deepahora cubreextract_content, la longitud del contenido, los patrones de inclusión/exclusión,follow_external,respect_robots,concurrency, el filtro de dominio y la sesión. La demap_sitecubresearch, el filtro de dominio,include_metadataygroup_by_path. Antes, una llamada cacheada podía contradecir tus parámetros durante toda la hora del TTL. - Codificación de caracteres. Los cuerpos de respuesta ahora se decodifican con su charset declarado (cabecera
Content-Typeo detección de<meta charset>) en lugar de asumir siempre UTF-8. Se acabó el texto corrupto con U+FFFD en sitios ISO-8859-1 o Shift_JIS. - Opciones descartadas en silencio. Los esquemas de
optionsdeextract_content,summarize_contentyanalyze_contentahora usan.passthrough(). Antes, todas las claves de opción documentadas se descartaban antes de llegar al handler, y por esosummarize_contentdevolvía siempre el mismo fallback de 2 frases mal etiquetado comoextractive. El resumidor extractivo ahora se ejecuta de verdad, ysummaryLengthcambia la salida. - Resolución de enlaces.
extract_linksresuelve los href relativos contra la URL final de la página en lugar de contra el origen, respeta<base href>y clasifica los enlaces relativos al protocolo como externos. Los mismos arreglos llegaron al extractor de enlaces descrape, así que por fin coinciden. - Similitud de
track_changes. La similitud de contenido ahora es Jaccard por tokens sobre el contenido. Antes era distancia de Hamming entre digests hexadecimales sha256, lo que significa que cualquier edición trivial puntuaba en torno al 0% de similitud y disparaba una alerta de cambio "moderado". - Puntuación de
search_web. Losranking_weightsparciales ahora se fusionan en profundidad sobre los valores por defecto en lugar de reemplazarlos por completo, así que ya no obtienes puntuaciones finalesNaNni comprobaciones de duplicados desactivadas en silencio. El reintento de expansión ante cero resultados está limitado a un solo fallback en lugar de hasta cinco búsquedas facturadas al backend.
Fase 3: seguro para ejecutarse durante días
La fase 3 cerró 24 hallazgos de la categoría que solo aparece en procesos de larga duración.
Ciclo de vida del navegador. Cerrar una página de Playwright no cierra su contexto, así que cada llamada a scrape_with_actions y cada extract_content renderizado en navegador filtraba un contexto hasta el apagado. Los contextos sin stealth ahora se cierran junto con su página. Un page.goto fallido (error de DNS, timeout, URL bloqueada) dejaba huérfanos una página y un contexto vivos; ahora ambos se desmontan.
Cachés acotadas. crawl_deep destruye su CacheManager por crawl en un finally. Antes, N crawls filtraban permanentemente N cachés de hasta 1.000 documentos HTML completos cada una, y todas ellas reejecutaban un escaneo de memoria con JSON.stringify cada 60 segundos para siempre. Las instancias descartadas ahora se verifican por GC con un test de regresión con WeakRef. Los resultados de batch_scrape tienen un límite LRU de 20 lotes más expulsión por TTL.
Plazos en cada lectura de cuerpo. El temporizador de aborto ahora sigue armado durante el flujo del cuerpo, así que el parámetro timeout por fin cubre a un servidor que devuelve cabeceras y luego se atasca en el cuerpo. El reensamblado de chunks es de una sola pasada; era O(n²), unos 1,5 segundos de bloqueo síncrono del bucle de eventos en un cuerpo de 25 MB. Las descargas de PDF recibieron un AbortSignal.timeout real de 30 segundos (la antigua opción timeout: de fetch-init la ignoraba undici en silencio), y el proveedor SearXNG recibió 15 segundos en lugar de los ~5 minutos por defecto de undici.
Un arreglo que merece mención para quienes usan Claude Desktop: el almacenamiento de snapshots ahora usa por defecto ~/.crawlforge/snapshots en lugar de process.cwd(). Clientes MCP como Claude Desktop lanzan el servidor con directorio de trabajo /, donde toda escritura de snapshot fallaba en silencio.
Fase 4: el despliegue remoto y HTTP ya funciona
Si desplegaste CrawlForge con npm run start:http, estaba peor de lo que creías: un único transporte compartido significaba que solo existía una sesión, y cualquier desconexión limpia dejaba /mcp inservible hasta reiniciar el proceso.
El modo con estado ahora sigue el patrón por sesión documentado del SDK: un Map<sessionId, {transport, server}> con un transporte nuevo y un McpServer clonado por cada initialize, liberación al hacer DELETE y un 404 JSON-RPC para IDs de sesión desconocidos. Un segundo cliente concurrente, una reconexión tras una caída de red y un DELETE seguido de un initialize nuevo ahora funcionan.
También en la fase 4:
- El prompt
getting-startedera irrecuperable para cualquier cliente: el objeto de configuración caía en la sobrecarga posicional deargsSchemadel SDK, anunciando un argumento requerido inexistente y haciendo fallar todos losprompts/get. Arreglado, y la suite de conformidad ahora cubre el descubrimiento y la recuperación de los 6 prompts registrados. - Las firmas HMAC de webhooks ahora cubren exactamente el cuerpo serializado que se envía por POST. Solo se firmaba el subobjeto
data, así que la verificación estándar del receptor sobre el cuerpo en bruto fallaba siempre. scrapeya no incrusta megabytes de bytes base64 de captura de pantalla en el resultado JSON: una vez almacenada, el resultado solo conserva los metadatos y el URI de recursocrawlforge://screenshot/{id}.- Los banners de estado del autoarranque pasaron de stdout a stderr, así que un primer lanzamiento con
CRAWLFORGE_API_KEYdefinida ya no inyecta líneas no-JSON en el canal JSON-RPC de stdio. search_webrecurre a la API key de~/.crawlforge/config.jsoncuando faltaCRAWLFORGE_API_KEY. Quienes se configuraban connpm run setuppasaban la comprobación de credits y luego chocaban con un fallo garantizado del adaptador, con medio cargo de 2 credits por llamada.
Fase 5: cero vulnerabilidades en npm audit
Con el mínimo de Node 20 ya establecido, la fase 5 retiró todas las dependencias abandonadas y aplicó las actualizaciones de seguridad que el mínimo anterior bloqueaba. npm audit pasó de 4 moderadas a 0.
Eliminadas por completo: node-cron (sin uso desde que la fase 3 movió la planificación de monitores a temporizadores setInterval; su eliminación despejó su cadena vulnerable de uuid), @googleapis/customsearch (sin uso: el adaptador de Google llama directamente al endpoint REST) y node-summarizer (abandonada desde 2019; el resumidor extractivo se reescribió como un puntuador de frecuencia de palabras estilo Luhn basado en compromise, con formas de resultado idénticas).
La actualización que más importó: pdf-parse 1.1.1 → 2.4.5. PDFProcessor se portó a la API de clases de la v2, lo que significa que la opción password ahora descifra de verdad los PDF protegidos; la v1 la ignoraba en silencio. La extracción por rango de páginas usa la extracción parcial nativa de la v2, y la marca de metadatos cifrados lee el EncryptFilterName real de pdfjs-dist.
Sobre la cadena de suministro: esta fase se ejecutó durante el gusano de npm ChainDrop (activo desde el 4 de agosto de 2026). Todas las instalaciones se hicieron con --ignore-scripts, todas las versiones adoptadas se limitaron por fecha de publicación a antes del 4 de agosto de 2026, y el diff completo del lockfile se contrastó con las listas de paquetes comprometidos de Socket y StepSecurity sin ninguna coincidencia. Los escaneos de IoC quedaron limpios antes y después.
Fase 6: adopción de la especificación MCP
La última fase puso a CrawlForge al día con la especificación MCP actual.
Salida estructurada (MCP 2025-06-18). scrape, map_site, serp_rank, search_web, extract_structured y crawl_deep ahora declaran un outputSchema y devuelven structuredContent junto al texto JSON heredado. Los esquemas son permisivos por diseño, así que un resultado legítimo nunca puede fallar la validación de salida del SDK.
Tareas asíncronas. crawl_deep, batch_scrape, deep_research y agent se registran con taskSupport: 'optional' bajo la extensión io.modelcontextprotocol/tasks. Los clientes compatibles con tareas reciben un identificador de inmediato y consultan tasks/get; los clientes sin soporte de tareas siguen recibiendo el resultado síncrono exactamente igual que antes. Esta es la solución para los crawls largos que expiraban dentro de la ventana de llamada a herramienta de un cliente.
Selección de herramientas en el cliente. Dos nuevas variables de entorno te permiten exponer un subconjunto de las 27 herramientas y reducir la saturación de contexto:
# By name
CRAWLFORGE_TOOLS=scrape,search_web,extract_content
# Or by group — 12 available: basic, search, crawl, extract, batch,
# research, tracking, llmstxt, stealth, templates, scrape, agent
CRAWLFORGE_TOOL_GROUPS=search,extractSin definir significa todas las herramientas. Los nombres desconocidos se ignoran con un aviso por stderr, batch_scrape habilita automáticamente get_batch_results, y el banner de arranque informa de cuántas están habilitadas sobre el total.
Higiene del protocolo. Los esquemas de herramienta se anuncian en JSON Schema 2020-12 en lugar de draft-07. tools/list se ordena de forma determinista para dar estabilidad a la caché de prompts del cliente. Los argumentos de herramienta inválidos vuelven como resultados con isError: true —de los que un modelo puede autocorregirse— en lugar de errores de protocolo -32602. Los iconos se incluyen en serverInfo, en cada herramienta y en cada prompt.
Registro MCP. server.json está completo según el esquema de registro del 11 de diciembre de 2025, con un flujo de publicación por OIDC de GitHub que publica en registry.modelcontextprotocol.io en la próxima versión.
Novedades desde v4.8.0: serp_rank y guiado de herramientas
Si tu última actualización fue a v4.8.0, entremedias llegaron dos versiones menores.
v4.9.0 añadió serp_rank, la herramienta número 27: posiciones reales de ranking orgánico de Google vía DataForSEO, a 5 credits por consulta configurada. v4.10.0 hizo que devuelva el listado orgánico completo del top-10 junto a las posiciones de tu dominio objetivo.
v4.10.0 también añadió instructions a nivel de servidor en MCP. El servidor ahora indica a cualquier cliente que se conecte que prefiera las herramientas de CrawlForge sobre sus propias capacidades web integradas para búsqueda, fetch, crawl e investigación. Como viaja en el binario del servidor, todos los clientes MCP lo recogen automáticamente en el siguiente arranque tras actualizar, sin necesidad de volver a ejecutar init. Es una guía, no una imposición: un MCP server no puede desactivar las herramientas integradas de un cliente.
Precios: 27 herramientas medidas, sin cambios
En v5.0.0 no cambió ningún precio. Las 27 herramientas están medidas y requieren una API key, a entre 1 y 10 credits por llamada.
| Plan | Precio | Credits |
|---|---|---|
| Free | pago único (sin tarjeta) | 1.000 credits de prueba |
| Hobby | $19/mes | 5.000 |
| Professional | $99/mes | 50.000 |
| Business | $399/mes | 250.000 |
Todos los planes incluyen todas las herramientas. La extracción con LLM usa por defecto Ollama local, así que no necesitas una key de OpenAI ni de Anthropic salvo que decidas usarla.
Cómo actualizar
Comprueba primero tu versión de Node; es lo único que puede darte problemas:
node --version # must be >= 20.16.0Después:
npm install -g crawlforge-mcp-server@latestUsuarios nuevos:
npm install -g crawlforge-mcp-server
npx crawlforge initQuienes ya usan un cliente MCP también pueden simplemente forzar una reconexión con /mcp. Como la fase 2 arregló el comportamiento de las herramientas y no sus esquemas, tus llamadas actuales siguen funcionando: solo que ahora devuelven resultados correctos.
Qué viene a continuación
Varias vías de la fase 6 se aplazaron deliberadamente en lugar de precipitarse: un endpoint remoto alojado con OAuth, un nivel sin key, monitorización programada como servicio, sesiones persistentes y redacción de PII. La migración al SDK v2 está en cola tras una decisión sobre el mínimo de Node 22.
Mientras tanto, sigue en pie la invitación de v4.8.0. Si encuentras un control que no se comporta como afirma la documentación, ese es exactamente el bug que queremos conocer.
¿Listo para probarlo? Empieza gratis con 1.000 credits — y luego ejecuta npx crawlforge init para registrar el MCP server. Consulta la documentación completa, la referencia de serp_rank o el post de lanzamiento de v4.8.0 para ver lo que vino antes.
Pruébalo tú mismo — sin necesidad de registrarte
Ejecuta cualquiera de las 27 herramientas de scraping y extracción de CrawlForge en el playground y luego empieza gratis con 1,000 credits.
1,000 credits gratis • Por única vez • No se requiere tarjeta de crédito
Etiquetas
Sobre el autor
Mantente al día con los últimos artículos
Recibe tutoriales, novedades del producto y consejos de web scraping en tu bandeja de entrada.
Sin spam. Cancela tu suscripción cuando quieras.