Skip to main content
Glama

local-web-mcp

Versión 0.3.0 · AGPL-3.0

Esta herramienta se ha desarrollado con apoyo de IA, pero ha sido revisada por una persona antes de su publicación.

Un servidor MCP que le da a Claude un recuperador web de respaldo que se ejecuta en tu propia máquina. Cuando el recuperador integrado está bloqueado, este lo intenta desde tu IP, tu conexión y, opcionalmente, tu sesión iniciada.

Una única herramienta: fetch_url_locally.

El problema que resuelve

Los recuperadores alojados se ejecutan desde rangos de IP de centros de datos, que muchos sitios rechazan directamente. Un servidor MCP local por stdio no: el cliente lanza el proceso en tu máquina, por lo que las solicitudes se originan desde tu conexión habitual.

Funcionamiento verificado en sitios que el recuperador alojado no podía leer, incluidos CNBC, Politiken y Bloomberg.

Related MCP server: auth-fetch-mcp

Lo que no cambia

Conviene decirlo claramente, porque el planteamiento invita a exagerar.

  • La inferencia del modelo sigue ejecutándose en los servidores de Anthropic.

  • El texto de la página recuperada se sigue enviando al modelo como salida de la herramienta. Todo lo que se lea a través de una sesión autenticada se incluye con él.

  • Cambia quién habla con el sitio web, no dónde se ejecuta el modelo.

El límite infranqueable

¿Se puede leer la página sin ejecutar JavaScript?

Si es así, esto se encarga. Si no, nada en la capa de cabeceras, TLS o cookies conseguirá llegar, y ningún ajuste de User-Agent servirá de ayuda. Los sitios que usan DataDome, Cloudflare Turnstile, PerimeterX y similares presentan un desafío que debe ejecutarse para superarlo. Para esos, usa una herramienta basada en navegador o abre la página tú mismo.

Es un límite que hay que conocer, no un error que haya que corregir.

Veredictos

Cada respuesta viene etiquetada. El caso peligroso no es un 403 evidente, sino un 200 que no es la página: un intersticial antibots, un muro de consentimiento, una cáscara vacía renderizada en el cliente. Esos se resumen como si fueran el artículo.

Veredicto

Significado

Qué hacer

ok

Contenido real

Úsalo

challenge

Protección antibots detectada

Requiere navegador, detente

blocked

Rechazado directamente (403), normalmente detección de bots

Requiere navegador, detente

js_required

Cáscara renderizada en el cliente, sin contenido sin JS

Requiere navegador, detente

login_required

401, muro de inicio de sesión o muro de suscripción

Las cookies pueden ayudar

http_error

Cualquier otro estado no 2xx (404, 429, 5xx)

Reintenta más tarde solo para 429/5xx

empty

Menos de 200 caracteres extraídos

Lectura fallida, no una página vacía

Cualquier cosa que no sea ok añade una advertencia explícita que le dice al modelo que no trate el cuerpo como contenido.

La evidencia del cuerpo tiene más peso que el código de estado. Un editor que sirve un artículo de pago como HTTP 403 se informa como login_required, no como blocked, porque el consejo útil ahí es exportar las cookies en lugar de recurrir a un navegador.

La detección se basa en la infraestructura del proveedor en lugar del texto: las páginas de desafío están localizadas, así que captcha-delivery.com es una señal fiable donde «verificando tu dispositivo» no lo es. Las cookies de proveedores en las cabeceras de respuesta cuentan como evidencia cuando se combinan con un estado de rechazo.

La herramienta

fetch_url_locally(url, max_chars=20000, use_session=true)

Parámetro

Tipo

Por defecto

Propósito

url

string

obligatorio

La página que se va a recuperar. Solo http y https

max_chars

integer

20000

Límite del texto devuelto, limitado a 200000. El truncamiento se indica en la cabecera

use_session

boolean

true

Envía cookies. Pasa false para comprobar si una página es realmente pública

La respuesta es una cabecera breve seguida del texto extraído:

URL: https://example.com/article
Status: 200
Verdict: ok
Title: The headline
Session: authenticated (the user's cookies were sent)

The article text...

Session: aparece solo cuando las cookies se cargaron realmente y estaban limitadas a ese host. Un veredicto distinto de ok añade una línea WARNING: que indica al modelo que no trate el cuerpo como contenido.

Los fallos se devuelven como un error que indica la causa, por ejemplo [blocked_host] Host '192.168.1.5' resolves to a private or internal address. Códigos: invalid_url, blocked_scheme, blocked_host, dns_failure, timeout, too_many_redirects, upstream_error, invalid_argument.

Requisitos

  • Python 3.11+ (usa asyncio.timeout). Con uv no necesitas instalarlo tú mismo; uv descarga un intérprete adecuado

  • Claude Desktop o Claude Code. Los servidores Stdio no funcionan en el navegador ni en la aplicación móvil, que requieren un endpoint HTTPS accesible públicamente.

Instalación

Con uv, que descarga un Python adecuado y las dependencias por sí mismo:

uv --directory /absolute/path/to/local-web-mcp run local-web-mcp

Ejecuta eso una vez en una terminal antes de registrar el servidor. La primera ejecución resuelve y construye el entorno, lo que tarda lo suficiente como para que un cliente que lo lance en frío pueda rendirse y notificar que el servidor ha fallado aunque la configuración sea correcta.

Imprime Starting local-web y luego espera a un cliente en stdin, que es el aspecto de un servidor en funcionamiento. En cuanto veas esa línea, el entorno está construido: pulsa Ctrl+C y continúa.

O con un entorno virtual simple:

python3 -m venv .venv
.venv/bin/pip install -r requirements.txt

Registro con Claude Desktop

Añádelo a claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Linux: ~/.config/Claude/):

{
  "mcpServers": {
    "local-web": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/local-web-mcp",
        "run",
        "local-web-mcp"
      ]
    }
  }
}

Si uv no está en el PATH que ve el cliente, usa su ruta absoluta como command. El equivalente con el entorno virtual es:

{
  "mcpServers": {
    "local-web": {
      "command": "/absolute/path/to/.venv/bin/python",
      "args": ["/absolute/path/to/local_web_mcp.py"]
    }
  }
}

Claude Code:

claude mcp add local-web -- uv --directory /absolute/path/to/local-web-mcp run local-web-mcp

Configuración

Todo es opcional. Cada ajuste tiene un valor predeterminado que funciona.

Variable

Por defecto

Propósito

LOCALWEB_COOKIE_FILE

sin definir

Ruta a un archivo de cookies

LOCALWEB_COOKIE_DOMAINS

sin definir

Dominios para los que se puede usar el archivo. Establécelo siempre que definas un archivo de cookies

LOCALWEB_ALLOW_PRIVATE

false

Permitir destinos privados, de bucle local y de enlace local

LOCALWEB_ALLOWLIST

vacío

Nombres de host exentos de la comprobación de IP

LOCALWEB_USER_AGENT

Chrome UA

Se envía en cada solicitud

LOCALWEB_ACCEPT_LANGUAGE

da,en-GB;q=0.9,en;q=0.8

Preferencia de idioma. Los sitios la usan para elegir un idioma y a veces una edición regional

LOCALWEB_CONNECT_TIMEOUT

5

Segundos

LOCALWEB_READ_TIMEOUT

20

Segundos

LOCALWEB_TOTAL_TIMEOUT

40

Tope máximo por llamada

LOCALWEB_MAX_BYTES

3000000

Tope del cuerpo de la respuesta

LOCALWEB_MAX_REDIRECTS

5

Saltos de redirección, compartidos con los meta refrescos

El Accept-Language predeterminado pide danés primero. Es un valor predeterminado deliberado y no neutro, así que define LOCALWEB_ACCEPT_LANGUAGE si quieres inglés o cualquier otra cosa:

"env": { "LOCALWEB_ACCEPT_LANGUAGE": "en-GB,en;q=0.9" }

Cookies de sesión

Apunta LOCALWEB_COOKIE_FILE a una exportación de una extensión de navegador. El cargador acepta cookies.txt de Netscape con cualquier cabecera o sin ninguna, y exportaciones JSON de las extensiones habituales. Consulta cookies.txt.example.

Define siempre LOCALWEB_COOKIE_DOMAINS. Sin ello, todo el archivo está activo y cualquier recuperación puede llevar una sesión no relacionada. Con ello, cualquier cookie fuera de esos dominios se descarta en el momento de la carga, antes de que el archivo llegue a un cliente. La coincidencia cubre subdominios (example.com cubre www.example.com), pero no imitaciones (evil-example.com).

Tres cosas a tener en cuenta:

  1. El contenido leído a través de tu sesión se envía al modelo como salida de la herramienta.

  2. Un archivo de cookies es un archivo de credenciales. Haz chmod 600, y aquí está en el .gitignore.

  3. Las cookies caducan. Una fuente que antes funcionaba y devuelve login_required suele ser una exportación caducada, no una pérdida de acceso.

Pasa use_session=false para comprobar si una página es realmente pública.

Acceso a una red local

Las direcciones privadas están bloqueadas por defecto, y de forma deliberada. El modelo elige las URLs en parte a partir del texto que acaba de leer, por lo que una página recuperada puede intentar dirigirlo hacia 192.168.1.1. La lista de bloqueo hace que una inyección de instrucciones en el contenido de la página no pueda convertir esto en un escáner de red.

Prefiere una lista de permitidos limitada antes que el interruptor general:

"env": { "LOCALWEB_ALLOWLIST": "nas.local,nas" }

Seguridad

  • Esquema restringido a http y https; se rechazan las URLs que contienen credenciales

  • Nombre de host resuelto y cada dirección devuelta validada antes de la solicitud

  • El IPv4 mapeado en IPv6 (::ffff:10.0.0.1) se desenvuelve antes de la comprobación

  • Los endpoints de metadatos de la nube están bloqueados incondicionalmente: el nombre de host se resuelve antes que la lista de permitidos y que ALLOW_PRIVATE, por lo que ninguno de los dos puede abrirlos

  • Las redirecciones y los meta refrescos se siguen manualmente y se revalidan en cada salto

  • Se registran los recuentos de cookies, nunca nombres, valores ni dominios

Limitaciones conocidas

  • Sin JavaScript. El límite infranqueable mencionado antes.

  • DNS rebinding. El nombre de host se resuelve para la validación y luego se resuelve de nuevo al conectar. Cerrar esa brecha requiere fijar la conexión a la IP validada. Merece la pena hacerlo antes de activar ALLOW_PRIVATE en una red no confiable.

  • La detección de desafíos se basa en firmas y quedará obsoleta a medida que los proveedores cambien su marcado. Ejecuta inspect_response.py si un veredicto parece incorrecto.

  • La extracción de HTML a texto no tiene dependencias y es rudimentaria. trafilatura sería notablemente mejor para la extracción seria de artículos.

Archivos

Archivo

Propósito

local_web_mcp.py

El servidor

cookies.py

Cargador de cookies tolerante. Requerido, importado por el servidor

inspect_response.py

Diagnóstico: vuelca lo que el recuperador recibe realmente

unit_test.py

Veredictos, validación de destinos, carga y ámbito de cookies

smoke_test.py

Destinos bloqueados y una recuperación en vivo, a través de stdio

cookies.txt.example

Plantilla anotada para un archivo de cookies

pyproject.toml

Metadatos del paquete y el punto de entrada local-web-mcp

uv.lock

Versiones de dependencias fijadas para instalaciones reproducibles

requirements.txt

Dependencias de ejecución para la ruta del entorno virtual simple

.gitignore

Excluye el venv, las cachés y cualquier archivo de cookies

LICENSE

Texto completo de AGPL-3.0

Diagnóstico de un veredicto incorrecto

uv run python inspect_response.py https://example.com/article

Imprime el estado, las cabeceras interesantes, el comienzo del cuerpo y, a continuación, ejecuta la detección del propio servidor sobre ello. Compruébalo siempre antes de cambiar la lógica de detección. Con frecuencia, un navegador y este recuperador reciben respuestas totalmente distintas, por lo que lo que ves en pantalla no es evidencia de lo que recibió la herramienta.

Pruebas

uv run python unit_test.py
uv run python smoke_test.py

unit_test.py funciona sin conexión y termina con un código de salida distinto de cero en caso de error, por lo que sirve como puerta de pre-commit. smoke_test.py controla el servidor mediante stdio y hace una solicitud real, por lo que necesita conexión de red. Ejecute ambos desde la raíz del repositorio.

En la ruta de venv simple, sustituya .venv/bin/python por uv run python.

Licencia

Copyright (C) 2026 David Lindholm.

GNU Affero General Public License v3.0 o posterior. Véase LICENSE.

Este programa se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANTÍA; incluso sin la garantía implícita de COMERCIABILIDAD o IDONEIDAD PARA UN FIN PARTICULAR.

A
license - permissive license
Not graded
quality - not tested
Not graded
maintenance - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Fetches content from authenticated web pages by driving your signed-in Chrome/Edge browser via DevTools Protocol, automatically handling login redirects and reusing sessions across domains.
    8
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI assistants to access content from authenticated web pages by opening a real browser for manual login and session capture. It saves browser profiles locally so users only need to log in once per service for future automated access.
    4
    69
    35
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI agents to control the user's Chrome or Firefox browser, leveraging existing sessions for tasks requiring authentication and user handoff.
    18
    17
    15
    MIT

View all related MCP servers

Related MCP Connectors

  • Reliable web access for AI agents: smart HTTP, rotating proxies, and full-browser rendering.

  • Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.

  • Provides cloud browser automation capabilities using Stagehand and Browserbase, enabling LLMs to i…

View all MCP Connectors

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/davidwlindholm/local-web-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server