Skip to main content
Glama
JohnnyFoulds

markdown-for-agents-mcp

markdown-for-agents-mcp

npm version npm downloads Node.js codecov License: MIT

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 structuredContent tipado (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 entorno HTTP_PORT) con autenticación opcional mediante token bearer.

  • Soporte de proxy — Pasa PLAYWRIGHT_PROXY para enrutar el tráfico de Playwright a través de un proxy.

  • Monitoreo de salud — La herramienta health_check expone 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-mcp

Chromium 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-mcp

Configuració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-mcp

Todo 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-mcp

Los 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

url

string

URL a obtener y convertir

timeout

number

no

Tiempo de espera de la solicitud en ms (anula FETCH_TIMEOUT_MS)

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

urls

string[]

URLs a obtener

timeout

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).


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

query

string

Consulta de búsqueda

maxResults

number

no

Máximo de resultados a devolver (predeterminado: 10)

allowedDomains

string[]

no

Solo incluir resultados de estos dominios

blockedDomains

string[]

no

Excluir resultados de estos dominios

fetchResults

boolean

no

Obtener y convertir las páginas de resultados principales a Markdown

timeout

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 allowedDomains y blockedDomains se aplican solo al filtrado de resultados de búsqueda. La configuración a nivel de servidor BLOCKLIST_DOMAINS / USE_ALLOWLIST_MODE sigue 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

url

string

URL del archivo a descargar

outputPath

string

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 por fetch_url (para evitar cadenas de descarga binaria). Usa fetch_url para páginas HTML; download_file rechazará respuestas text/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.com

Múltiples URLs (modo por lotes)

markdown-cli -b https://example.com https://example.org https://example.net

Guardar en archivo

markdown-cli https://example.com/article > article.md

Descargar un archivo binario

markdown-cli -d -o /tmp/report.pdf https://example.com/report.pdf

Referencia de comandos

Comando

Descripción

markdown-cli <url>

Obtener una sola URL e imprimir Markdown

markdown-cli -b <url1> <url2> ...

Obtener múltiples URLs en modo por lotes

markdown-cli -d -o <path> <url>

Descargar un archivo binario a una ruta local

markdown-cli --help

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 .env

Referencia

Variable

Predeterminado

Descripción

FETCH_TIMEOUT_MS

30000

Tiempo de espera por solicitud de obtención (ms)

MAX_CONCURRENT_FETCHES

5

Máximo de obtenciones paralelas en operaciones por lotes

MAX_REDIRECTS

10

Máximo de saltos de redirección antes de error

MAX_CONTENT_LENGTH

100000

Tamaño máximo de contenido (caracteres) antes de truncar

LOG_LEVEL

INFO

DEBUG, INFO, WARN o ERROR

LOG_FORMAT

text

text (legible por humanos) o json (estructurado)

CACHE_MAX_BYTES

52428800

Tamaño máximo de caché LRU (50 MB)

CACHE_TTL_MS

900000

TTL de entrada de caché (15 minutos)

USE_ALLOWLIST_MODE

false

Cuando es true, solo se permiten dominios en BLOCKLIST_DOMAINS

BLOCKLIST_DOMAINS

(vacío)

Dominios separados por comas para bloquear (o permitir en modo lista de permitidos)

BLOCKLIST_URL_PATTERNS

(vacío)

Patrones regex separados por comas para bloquear por ruta de URL

WEB_SEARCH_DEFAULT_TIMEOUT_MS

30000

Tiempo de espera predeterminado para solicitudes de búsqueda (ms)

DOWNLOAD_TIMEOUT_MS

60000

Tiempo de espera para descargas de archivos binarios (ms)

HTTP_PORT

(sin establecer)

Cuando se establece, inicia un servidor HTTP en este puerto en lugar de stdio

MCP_AUTH_TOKEN

(sin establecer)

Token bearer requerido en todas las solicitudes HTTP (solo modo HTTP)

PLAYWRIGHT_PROXY

(sin establecer)

URL del servidor proxy para Playwright (ej. http://proxy.example.com:8080)

PLAYWRIGHT_PROXY_BYPASS

(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

-
security - not tested
A
license - permissive license
-
quality - not tested

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