markdown-for-agents-mcp
markdown-for-agents-mcp
Un servidor MCP (Model Context Protocol) que obtiene URLs con renderizado completo de JavaScript y las convierte a Markdown limpio y eficiente en tokens para agentes de IA.
La mayoría de las herramientas de obtención MCP utilizan HTTP simple: ven lo que envía un servidor sin ejecutar nada de JavaScript. Eso funciona para sitios estáticos, pero devuelve silenciosamente contenido vacío o roto para React, Vue, Angular, SPAs y cualquier página que cargue datos dinámicamente. Este servidor ejecuta un navegador Chromium real a través de Playwright, por lo que renderiza la página completa antes de la extracción: el mismo contenido que vería un usuario humano.
Impulsado por Playwright y la biblioteca markdown-for-agents. Elimina anuncios, navegación y código repetitivo, entregando hasta un 80% menos de tokens que el HTML sin procesar.
¿Por qué Playwright?
Capacidad | Capturadores HTTP simples | markdown-for-agents-mcp |
Páginas HTML estáticas | ✅ | ✅ |
Aplicaciones React / Vue / Angular | ❌ | ✅ |
Contenido renderizado por JavaScript | ❌ | ✅ |
Rutas de aplicaciones de una sola página | ❌ | ✅ |
Carga diferida / scroll infinito | ❌ | ✅ |
Eficiencia de tokens vs HTML sin procesar | Media | Hasta 80% menos |
Evasión de detección de bots | Ninguna | Rotación de UA, suplantación de webdriver |
Ejemplo de reducción de tokens: una página de artículo de noticias típica tiene ~150 KB de HTML sin procesar (~40,000 tokens). Después del renderizado de Playwright, la poda del DOM y la conversión a Markdown, el mismo artículo se convierte en ~2,000 tokens: una reducción del 95%.
Tabla de contenidos
Características
Renderizado de JavaScript — Chromium impulsado por Playwright renderiza React, Vue, Angular y cualquier página con carga intensiva de JS antes de la extracción.
Salida estructurada — Las herramientas devuelven
structuredContenttipado (url, title, markdown, fetchedAt, contentSize) junto con la respuesta de texto, compatible con MCP SDK 1.11+.Extracción inteligente de contenido — Califica y selecciona el bloque de contenido principal (
main>article>#content>body), eliminando barras laterales, navegación y anuncios automáticamente.Eficiencia de tokens — Produce Markdown compacto listo para LLM; los benchmarks muestran hasta un 80% menos de tokens que el HTML sin procesar.
Búsqueda web — Búsqueda en DuckDuckGo con obtención y conversión opcional de los mejores resultados.
Caché LRU — Caché en memoria de 50 MB con un TTL de 15 minutos para evitar obtenciones redundantes.
Filtrado de dominios — Lista de bloqueo integrada de dominios de rastreadores/redes sociales; admite listas de permitidos/bloqueados por solicitud y modo de lista de permitidos a nivel de servidor.
Obtención por lotes — Obtenciones concurrentes de múltiples URLs con paralelismo configurable.
Modo servidor HTTP — Ejecutar como servidor HTTP (
--http [port]o variable de entornoHTTP_PORT) con autenticación opcional mediante token bearer.Soporte de proxy — Pasa
PLAYWRIGHT_PROXYpara enrutar el tráfico de Playwright a través de un proxy.Monitoreo de salud — La herramienta
health_checkexpone métricas de caché y obtención.Configuración cero — Chromium se instala automáticamente en la primera ejecución.
Instalación
npm install -g markdown-for-agents-mcpChromium se descarga automáticamente a través del script postinstall. Si falla, consulta Solución de problemas.
También puedes ejecutarlo sin instalar globalmente usando npx:
npx markdown-for-agents-mcpConfiguración del cliente MCP
Añade el servidor a la configuración de tu cliente MCP.
Claude Desktop
Edita ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) o %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"markdown": {
"command": "markdown-mcp"
}
}
}VS Code (Copilot / Continue)
Añade a tu espacio de trabajo o al settings.json de usuario bajo la clave de extensión MCP relevante, por ejemplo:
{
"mcpServers": {
"markdown": {
"command": "markdown-mcp"
}
}
}Cursor / Windsurf / Zed
Cualquier cliente que implemente la especificación MCP puede usar este servidor. El punto de entrada del comando es markdown-mcp (disponible en PATH después de la instalación global) o la ruta completa a dist/index.js para compilaciones locales.
Con anulaciones de variables de entorno
{
"mcpServers": {
"markdown": {
"command": "markdown-mcp",
"env": {
"FETCH_TIMEOUT_MS": "60000",
"LOG_LEVEL": "DEBUG"
}
}
}
}Modo servidor HTTP
En lugar de stdio, puedes ejecutar el servidor como un endpoint HTTP estándar, útil para despliegues compartidos, Docker o cualquier cliente que prefiera el transporte HTTP Streamable:
# Start on port 3456
markdown-mcp --http 3456
# Or use the env var
HTTP_PORT=3456 markdown-mcpTodo el tráfico MCP se maneja en POST|GET|DELETE /mcp. Para requerir un token bearer, establece MCP_AUTH_TOKEN:
MCP_AUTH_TOKEN=mysecrettoken HTTP_PORT=3456 markdown-mcpLos clientes deben pasar Authorization: Bearer mysecrettoken con cada solicitud.
Herramientas disponibles
fetch_url
Obtiene una sola URL con renderizado completo de JavaScript y devuelve Markdown limpio.
Argumentos:
Nombre | Tipo | Requerido | Descripción |
| string | sí | URL a obtener y convertir |
| number | no | Tiempo de espera de la solicitud en ms (anula |
Ejemplo:
fetch_url(url="https://example.com/blog/post")Salida de texto (siempre presente, compatible con versiones anteriores):
# Blog Post Title
Source: https://example.com/blog/post
This is the main content of the article, stripped of navigation, ads, and boilerplate.
## Related Section
More content here...
---
*Converted by markdown-for-agents-mcp*Salida estructurada (disponible para clientes MCP SDK 1.11+ a través de structuredContent):
{
"url": "https://example.com/blog/post",
"title": "Blog Post Title",
"markdown": "# Blog Post Title\n\nSource: ...",
"fetchedAt": "2026-04-06T17:00:00.000Z",
"contentSize": 2048
}fetch_urls
Obtiene múltiples URLs concurrentemente y devuelve Markdown combinado, una sección por URL.
Argumentos:
Nombre | Tipo | Requerido | Descripción |
| string[] | sí | URLs a obtener |
| number | no | Tiempo de espera por solicitud en ms |
Ejemplo:
fetch_urls(urls=[
"https://example.com/post1",
"https://example.com/post2"
])Salida de texto:
# Post 1 Title
Source: https://example.com/post1
...
---
# Post 2 Title
Source: https://example.com/post2
...
---Salida estructurada (a través de structuredContent):
{
"results": [
{
"url": "https://example.com/post1",
"title": "Post 1 Title",
"markdown": "...",
"fetchedAt": "2026-04-06T17:00:00.000Z",
"contentSize": 1820,
"success": true
},
{
"url": "https://example.com/post2",
"title": "Post 2 Title",
"markdown": "...",
"fetchedAt": "2026-04-06T17:00:00.000Z",
"contentSize": 2104,
"success": true
}
],
"summary": { "total": 2, "succeeded": 2, "failed": 0 }
}El paralelismo se controla mediante MAX_CONCURRENT_FETCHES (predeterminado: 5).
web_search
Busca en DuckDuckGo y opcionalmente obtiene los mejores resultados como Markdown. Utiliza un endpoint HTTP simple para evitar la detección de bots; no usa Playwright para la búsqueda en sí.
Argumentos:
Nombre | Tipo | Requerido | Descripción |
| string | sí | Consulta de búsqueda |
| number | no | Máximo de resultados a devolver (predeterminado: 10) |
| string[] | no | Solo incluir resultados de estos dominios |
| string[] | no | Excluir resultados de estos dominios |
| boolean | no | Obtener y convertir las páginas de resultados principales a Markdown |
| number | no | Tiempo de espera de la solicitud en ms |
Ejemplo — solo búsqueda:
web_search(
query="typescript tutorials",
maxResults=5,
allowedDomains=["typescriptlang.org", "github.com"]
)Ejemplo — búsqueda y obtención:
web_search(
query="react hooks guide",
fetchResults=true,
maxResults=3
)Salida de texto:
# Web Search Results
## Query: typescript tutorials
**Found 5 results in 1234ms**
### Results:
1. [TypeScript Handbook](https://www.typescriptlang.org/docs/)
The TypeScript Handbook provides comprehensive documentation...
2. [Best TypeScript Tutorials](https://github.com/danistefanovic/build-your-own-typescript)
Learn TypeScript by building your own compiler...Salida estructurada (a través de structuredContent):
{
"query": "typescript tutorials",
"results": [
{ "title": "TypeScript Handbook", "url": "https://www.typescriptlang.org/docs/", "snippet": "...", "domain": "typescriptlang.org" }
],
"fetchedContent": [
{ "url": "https://www.typescriptlang.org/docs/", "markdown": "..." }
],
"durationMs": 1234
}Nota: Los argumentos
allowedDomainsyblockedDomainsse aplican solo al filtrado de resultados de búsqueda. La configuración a nivel de servidorBLOCKLIST_DOMAINS/USE_ALLOWLIST_MODEsigue aplicándose cuando esos resultados se obtienen posteriormente.
download_file
Descarga un archivo binario (PDF, imagen, ZIP, etc.) desde una URL y lo guarda en una ruta local. Utiliza un cliente HTTP simple; no requiere Playwright. Se aplica la protección SSRF y la lista de bloqueo de dominios.
Argumentos:
Nombre | Tipo | Requerido | Descripción |
| string | sí | URL del archivo a descargar |
| string | sí | Ruta local absoluta donde guardar el archivo (el directorio padre debe existir) |
Ejemplo:
download_file(
url="https://example.com/report.pdf",
outputPath="/tmp/report.pdf"
)Salida:
{
"savedPath": "/tmp/report.pdf",
"sizeBytes": 204800,
"mimeType": "application/pdf",
"filename": "report.pdf"
}Nota: Las URLs con rutas como
/download/...están permitidas para esta herramienta aunque estén bloqueadas porfetch_url(para evitar cadenas de descarga binaria). Usafetch_urlpara páginas HTML;download_filerechazará respuestastext/html.
health_check
Devuelve el estado actual del servidor, métricas de caché y estadísticas de obtención. Útil para monitoreo y depuración.
Argumentos: ninguno
Ejemplo de salida:
{
"status": "healthy",
"cache": {
"hits": 47,
"misses": 15,
"currentSize": 12,
"totalBytes": 4194304,
"maxBytes": 52428800
},
"metrics": {
"totalFetches": 62,
"successCount": 59,
"errorCount": 3,
"avgDuration": 1840,
"cacheUtilization": 76
}
}Uso de CLI
Se incluye una CLI independiente (markdown-cli) para su uso fuera del protocolo MCP.
URL única
markdown-cli https://example.comMúltiples URLs (modo por lotes)
markdown-cli -b https://example.com https://example.org https://example.netGuardar en archivo
markdown-cli https://example.com/article > article.mdDescargar un archivo binario
markdown-cli -d -o /tmp/report.pdf https://example.com/report.pdfReferencia de comandos
Comando | Descripción |
| Obtener una sola URL e imprimir Markdown |
| Obtener múltiples URLs en modo por lotes |
| Descargar un archivo binario a una ruta local |
| Mostrar ayuda |
Configuración
Todos los ajustes se leen de las variables de entorno al inicio y se validan con Zod. Los valores no válidos provocan una salida distinta de cero con un error descriptivo.
Copia .env.example a .env para comenzar:
cp .env.example .envReferencia
Variable | Predeterminado | Descripción |
|
| Tiempo de espera por solicitud de obtención (ms) |
|
| Máximo de obtenciones paralelas en operaciones por lotes |
|
| Máximo de saltos de redirección antes de error |
|
| Tamaño máximo de contenido (caracteres) antes de truncar |
|
|
|
|
|
|
|
| Tamaño máximo de caché LRU (50 MB) |
|
| TTL de entrada de caché (15 minutos) |
|
| Cuando es |
| (vacío) | Dominios separados por comas para bloquear (o permitir en modo lista de permitidos) |
| (vacío) | Patrones regex separados por comas para bloquear por ruta de URL |
|
| Tiempo de espera predeterminado para solicitudes de búsqueda (ms) |
|
| Tiempo de espera para descargas de archivos binarios (ms) |
| (sin establecer) | Cuando se establece, inicia un servidor HTTP en este puerto en lugar de stdio |
| (sin establecer) | Token bearer requerido en todas las solicitudes HTTP (solo modo HTTP) |
| (sin establecer) | URL del servidor proxy para Playwright (ej. |
| (sin establecer) | Dominios separados por comas para omitir el proxy |
Todos los registros se escriben en stderr para mantener stdout limpio para el protocolo MCP.
Seguridad
Lista de bloqueo de dominios predeterminada
Los siguientes dominios están bloqueados de forma predeterminada para evitar obtenciones accidentales de rastreadores, redes publicitarias y plataformas sociales que bloquean agresivamente a los bots o sirven contenido de baja calidad:
doubleclick.net, facebook.com, twitter.com, tiktok.com, hotjar.com, mixpanel.com, bit.ly y aproximadamente otros 20 (consulta src/utils/domainBlacklist.ts para la lista completa).
Si necesitas obtener un dominio bloqueado
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/JohnnyFoulds/markdown-for-agents-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server