LlamaIndex + Scrapeless: Alimenta tu índice con páginas web en vivo.
Senior Web Scraping Engineer
Un índice de recuperación es tan actual como los documentos que incluyas en él. LlamaIndex maneja bien el troceado, la incrustación y la recuperación; la parte que se rompe silenciosamente es el paso antes de todo eso, donde las páginas web en vivo deben convertirse en texto limpio.
Conectar LlamaIndex al Servidor MCP de Scrapeless cubre ese paso. Las herramientas MCP devuelven las páginas renderizadas como markdown, LlamaIndex las envuelve como objetos Document, y el resto de tu pipeline de ingestión continúa sin cambios. Esta guía ejecuta la conexión, el descubrimiento de herramientas, una recuperación real de página y la división de documento a nodo de principio a fin.
Lo que Esta Configuración Le Da a Su Índice
Tu código de ingestión obtiene 21 herramientas llamadas desde una conexión, y llegan como herramientas nativas de LlamaIndex en lugar de algo que debas envolver tú mismo.
Los grupos son importantes para la ingestión:
- Recuperación de páginas —
scrape_markdowndevuelve una página ya convertida a markdown, que es el formato que mejor manejan tanto un divisor como un modelo de incrustación.scrape_htmlyscrape_screenshotdevuelven las otras dos formas. - Búsqueda —
google_searchygoogle_trendspermiten que un trabajo de ingestión descubra URLs en lugar de recibir una lista fija. - Control de navegador en vivo — dieciséis herramientas
browser_*para páginas que necesitan interacción antes de que exista el contenido.
El renderizado, el enrutamiento proxy y el manejo de acceso ocurren del lado del servidor, por lo que el proceso de ingestión sigue siendo un trabajo sencillo en Python sin necesidad de instalar un navegador.
Por qué el Servidor MCP de Scrapeless
La especificación del Protocolo de Contexto de Modelo define cómo un cliente descubre herramientas y sus esquemas de argumentos desde un servidor, lo que hace que esto sea diferente de escribir un helper de fetch: la lista de herramientas y los parámetros de cada herramienta llegan del servidor en lugar de estar codificados de forma fija en tu proyecto. Las llamadas viajan como mensajes JSON-RPC 2.0.
Scrapeless alberga el endpoint, por lo que no hay un proceso de servidor que ejecutar junto a tu indexador. La autenticación es solo un encabezado. El grupo browser_* está respaldado por el Navegador de Extracción Scrapeless, y los parámetros por herramienta están documentados en la documentación de Scrapeless.
Requisitos Previos
- Python 3.10 o posterior. Tanto
llama-index-corecomollama-index-tools-mcpdeclaran actualmente>=3.10,<4.0. - Una clave API de Scrapeless desde el tablero.
- Solo para la sección del agente: un paquete de integración de LLM como
llama-index-llms-openaimás la clave de ese proveedor.
Nota: Todo lo realizado en la sección de ingestión a continuación se ejecutó con una clave de Scrapeless y sin clave de proveedor de modelo. La conexión MCP, el descubrimiento de herramientas, los esquemas de argumentos, la llamada en vivo a la herramienta y la división de
Documenta nodo se ejecutaron. El paso del agente al final es una brecha de requisito previo: construir unFunctionAgentgeneraImportError: llama-index-llms-openai package not foundsin una integración de LLM instalada, por lo que ese bloque se muestra como el código que agregas en lugar de como salida capturada.
Instalación
bash
pip install "llama-index-tools-mcp==0.4.8"
Ese paquete trae consigo llama-index-core y el cliente mcp. Establece la clave en tu shell:
bash
export SCRAPELESS_API_KEY="your_api_key_here"
Conectar y Listar las Herramientas
BasicMCPClient toma la URL del endpoint y los encabezados; McpToolSpec convierte la lista de herramientas del servidor en herramientas de LlamaIndex:
python
import asyncio, os
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
async def main():
client = BasicMCPClient(
"https://api.scrapeless.com/mcp",
headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"]},
)
spec = McpToolSpec(client=client)
tools = await spec.to_tool_list_async()
print("conteo de herramientas:", len(tools))
print("nombres de muestra:", sorted(t.metadata.name for t in tools)[:6])
asyncio.run(main())
text
conteo de herramientas: 21
nombres de muestra: ['browser_click', 'browser_close', 'browser_create', 'browser_get_html', 'browser_get_text', 'browser_go_back']
La API es asíncrona en toda su extensión, por lo que el ejemplo se ejecuta dentro de asyncio.run. Los nombres de las herramientas llegan de manera plana, sin prefijo de servidor ni espacio de nombres con puntos, por lo que scrape_markdown es el nombre literal que tu código y tu agente usarán.
Tomar Solo las Herramientas Que Necesita el Trabajo
Un trabajo de ingestión rara vez necesita control de sesión del navegador. McpToolSpec acepta allowed_tools y devuelve solo aquellas, lo que mantiene la superficie pequeña y los esquemas fáciles de leer:
python
import asyncio, os
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
async def main():
client = BasicMCPClient(
"https://api.scrapeless.com/mcp",
headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"]},
)
spec = McpToolSpec(client=client, allowed_tools=["scrape_markdown"])
tools = await spec.to_tool_list_async()
tool = tools[0]
print("cantidad filtrada:", len(tools))
print("nombre:", tool.metadata.name)
print("campos de fn_schema:", list(tool.metadata.fn_schema.model_fields))
asyncio.run(main())
```text
cantidad filtrada: 1
nombre: scrape_markdown
campos de fn_schema: ['url']
El esquema proviene del servidor, por lo que es el contrato real en lugar de una suposición: scrape_markdown toma una sola url. LlamaIndex lo expone como fn_schema, el mismo modelo de Pydantic que un agente usaría para construir su llamada.
¿Listo para señalar esto a tus propias fuentes? Crea una cuenta gratuita en Scrapeless y conéctate con la clave de tu tablero.
Convierte Páginas en Vivo en Nodos
Esta es la parte que importa para la recuperación. Llama a la herramienta directamente, envuelve cada resultado como un Document con su fuente en los metadatos, luego divide en nodos:
python
import asyncio, os
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
from llama_index.core import Document
from llama_index.core.node_parser import SentenceSplitter
async def main():
client = BasicMCPClient(
"https://api.scrapeless.com/mcp",
headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"]},
)
spec = McpToolSpec(client=client, allowed_tools=["scrape_markdown"])
tool = (await spec.to_tool_list_async())[0]
urls = [
"https://quotes.toscrape.com/js/",
"https://quotes.toscrape.com/page/2/",
]
docs = []
for url in urls:
markdown = str(await tool.acall(url=url))
docs.append(Document(text=markdown, metadata={"source": url}))
print(f"documentos: {len(docs)}")
splitter = SentenceSplitter(chunk_size=256, chunk_overlap=32)
nodes = splitter.get_nodes_from_documents(docs)
print(f"nodos después de dividir: {len(nodes)}")
print(f"fuente del primer nodo: {nodes[0].metadata['source']}")
print(f"caracteres del primer nodo: {len(nodes[0].get_content())}")
asyncio.run(main())
text
documentos: 2
nodos después de dividir: 14
fuente del primer nodo: https://quotes.toscrape.com/js/
caracteres del primer nodo: 571
Varias cosas en esa salida merecen ser leídas con atención.
La primera URL es una página renderizada por el cliente: su contenido es escrito en el DOM por un script y aún así produjo markdown utilizable, porque el renderizado ocurrió del lado del servidor antes de la conversión. Una simple solicitud HTTP de esa misma URL devuelve un marcado sin ningún contenido en él.
chunk_size=256 cuenta tokens, no caracteres, razón por la cual el primer nodo tiene 571 caracteres de largo. Dimensionar un divisor en caracteres es una forma común de acabar con fragmentos que desbordan el contexto de un modelo de incrustación.
El metadata={"source": url} en cada Document sobrevive a la división y se encuentra en cada nodo derivado de él. Eso es lo que permite que un resultado de recuperación cite de dónde proviene, y es mucho más fácil adjuntarlo aquí que reconstruirlo más tarde.
Markdown es el formato intermedio adecuado para esto: los encabezados y enlaces sobreviven, mientras que los scripts, estilos y marcas de diseño no, por lo que el presupuesto de incrustación va al contenido.
Dale las Herramientas a un Agente
Una vez que las herramientas están en mano, un agente puede decidir cuál llamar en lugar de seguir una lista fija de URLs. Este paso necesita un paquete de integración de LLM y la clave del proveedor.
Nota: Este bloque es una brecha de requisito previo. Sin una integración de LLM instalada, construir el agente genera
ImportError: paquete llama-index-llms-openai no encontrado, por favor ejecuta pip install llama-index-llms-openai, por lo que no se muestra ninguna salida para ello.
python
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI
agent = FunctionAgent(
tools=tools,
llm=OpenAI(model="gpt-4.1-mini"),
system_prompt="Investiga páginas públicas y devuelve notas limpias con fuentes.",
)
response = await agent.run("Resumen de los autores citados en quotes.toscrape.com")
print(response)
Conclusión
Conectar LlamaIndex al Servidor MCP de Scrapeless requiere un cliente, una especificación de herramienta y un encabezado. El servidor suministra 21 herramientas con sus propios esquemas de argumentos, allowed_tools las reduce a lo que realmente necesita un trabajo de ingesta, y scrape_markdown devuelve páginas en el formato que tanto un divisor como un modelo de incrustación prefieren.
El hábito que vale la pena conservar es adjuntar la URL fuente como metadatos de Document en el momento de la recuperación. Cuesta un diccionario, sobrevive a la división de nodos y es lo que convierte un impacto de recuperación en una respuesta que puedes rastrear hasta una página.
Comience con el plan gratuito de Scrapeless para obtener una clave, consulte los precios de Scrapeless cuando dimensione una ejecución de ingestión y vea el resumen del servidor MCP de Scrapeless para la referencia completa de la herramienta.
Preguntas Frecuentes
P: ¿Cuál es el punto final del servidor Scrapeless MCP para LlamaIndex?
El punto final hospedado es https://api.scrapeless.com/mcp, al que se accede con su clave en el encabezado x-api-token a través de BasicMCPClient. No hay un proceso de servidor local para ejecutar, porque las herramientas se sirven de forma remota.
P: ¿Cuántas herramientas expone el servidor Scrapeless MCP a LlamaIndex?
Una conexión en vivo devuelve 21: dieciséis herramientas de control de sesión browser_*, tres herramientas de recuperación de páginas (scrape_markdown, scrape_html, scrape_screenshot), y dos herramientas de búsqueda (google_search, google_trends). Enumérelas en tiempo de ejecución en lugar de asumir, ya que un servidor puede agregar herramientas entre lanzamientos.
P: ¿Puedo cargar solo algunas herramientas MCP?
Sí. Pase allowed_tools=["scrape_markdown"] a McpToolSpec y la lista volverá solo con esa herramienta. Para la ingestión, vale la pena hacerlo: mantiene los esquemas legibles y evita que un agente abra sesiones de navegador que no necesita.
P: ¿Necesito una clave LLM para recuperar páginas a través de MCP?
No. La conexión, descubrimiento de herramientas, inspección de esquemas y tool.acall(...) directo funcionan solo con la clave de Scrapeless. Se necesita un proveedor de modelo una vez que entrega las herramientas a un agente, porque es entonces cuando algo tiene que decidir qué herramienta llamar.
P: ¿Por qué usar markdown en lugar de HTML para la recuperación?
Markdown mantiene la estructura que ayuda a la recuperación: encabezados, listas, enlaces, y elimina los scripts, estilos y marcas de diseño que consumen contexto de incrustación sin agregar significado. scrape_html sigue siendo la elección correcta cuando se pretende ejecutar sus propios selectores en lugar de incrustar el texto.
P: ¿Cómo puedo hacer un seguimiento de qué página provino un fragmento recuperado?
Coloque la URL en Document(metadata={"source": url}) cuando cree el documento. Esa metadata se copia en cada nodo que el separador deriva de él, por lo que cada fragmento recuperado lleva su origen sin ninguna contabilidad adicional.
P: ¿Qué debo verificar antes de ingerir un sitio?
Revise los términos del sitio y sus directrices en /robots.txt, que siguen el estándar del Protocolo de Exclusión de Robots. Mantenga la ingestión a páginas públicas, trabaje desde una lista de URL explícita o un paso de descubrimiento acotado, y registre la URL de origen en cada documento para que la procedencia de cualquier cosa que devuelva el índice siga siendo clara.
En Scrapeless, solo accedemos a datos disponibles públicamente y cumplimos estrictamente con las leyes, regulaciones y políticas de privacidad del sitio web aplicables. El contenido de este blog es sólo para fines de demostración y no implica ninguna actividad ilegal o infractora. No ofrecemos garantías y renunciamos a toda responsabilidad por el uso de la información de este blog o enlaces de terceros. Antes de realizar cualquier actividad de scraping, consulte a su asesor legal y revise los términos de servicio del sitio web de destino u obtenga los permisos necesarios.



