local-web-mcp
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 |
| Contenido real | Úsalo |
| Protección antibots detectada | Requiere navegador, detente |
| Rechazado directamente (403), normalmente detección de bots | Requiere navegador, detente |
| Cáscara renderizada en el cliente, sin contenido sin JS | Requiere navegador, detente |
| 401, muro de inicio de sesión o muro de suscripción | Las cookies pueden ayudar |
| Cualquier otro estado no 2xx (404, 429, 5xx) | Reintenta más tarde solo para 429/5xx |
| 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 |
| string | obligatorio | La página que se va a recuperar. Solo |
| integer |
| Límite del texto devuelto, limitado a 200000. El truncamiento se indica en la cabecera |
| boolean |
| Envía cookies. Pasa |
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 adecuadoClaude 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-mcpEjecuta 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.txtRegistro 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-mcpConfiguración
Todo es opcional. Cada ajuste tiene un valor predeterminado que funciona.
Variable | Por defecto | Propósito |
| sin definir | Ruta a un archivo de cookies |
| sin definir | Dominios para los que se puede usar el archivo. Establécelo siempre que definas un archivo de cookies |
|
| Permitir destinos privados, de bucle local y de enlace local |
| vacío | Nombres de host exentos de la comprobación de IP |
| Chrome UA | Se envía en cada solicitud |
|
| Preferencia de idioma. Los sitios la usan para elegir un idioma y a veces una edición regional |
|
| Segundos |
|
| Segundos |
|
| Tope máximo por llamada |
|
| Tope del cuerpo de la respuesta |
|
| 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:
El contenido leído a través de tu sesión se envía al modelo como salida de la herramienta.
Un archivo de cookies es un archivo de credenciales. Haz
chmod 600, y aquí está en el .gitignore.Las cookies caducan. Una fuente que antes funcionaba y devuelve
login_requiredsuele 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ónLos 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 abrirlosLas 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_PRIVATEen 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.pysi un veredicto parece incorrecto.La extracción de HTML a texto no tiene dependencias y es rudimentaria.
trafilaturasería notablemente mejor para la extracción seria de artículos.
Archivos
Archivo | Propósito |
| El servidor |
| Cargador de cookies tolerante. Requerido, importado por el servidor |
| Diagnóstico: vuelca lo que el recuperador recibe realmente |
| Veredictos, validación de destinos, carga y ámbito de cookies |
| Destinos bloqueados y una recuperación en vivo, a través de stdio |
| Plantilla anotada para un archivo de cookies |
| Metadatos del paquete y el punto de entrada |
| Versiones de dependencias fijadas para instalaciones reproducibles |
| Dependencias de ejecución para la ruta del entorno virtual simple |
| Excluye el venv, las cachés y cualquier archivo de cookies |
| Texto completo de AGPL-3.0 |
Diagnóstico de un veredicto incorrecto
uv run python inspect_response.py https://example.com/articleImprime 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.pyunit_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.
This server cannot be installed
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
- AlicenseNot gradedqualityAmaintenanceFetches 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.8MIT
- AlicenseAqualityAmaintenanceEnables 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.46935MIT
- AlicenseAqualityDmaintenanceEnables AI agents to control the user's Chrome or Firefox browser, leveraging existing sessions for tasks requiring authentication and user handoff.181715MIT
- FlicenseNot gradedqualityCmaintenanceUnlimited, session-authenticated web search and fetch for AI tools using your own browser. Supports authenticated/paywalled pages without API keys.
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…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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