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: Proxy Browser MCP Server

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.

Available Tools

1 tool
fetch_url_locallyFetch a URL from the user's machineA
Read-only

Fetch a web page over the user's own internet connection and return its readable text.

USE THIS WHEN the built-in web fetch has already been tried and: it returned an error, 403, or 429; it returned a Cloudflare or captcha interstitial; it returned a cookie/consent wall or a near-empty page; the source is geo-restricted; the source sits behind the user's institutional access or paid subscription; or the URL is on the user's local network.

DO NOT use it as the first attempt for ordinary public pages -- the built-in fetcher is faster and does not use the user's bandwidth.

The response carries a verdict line. If the verdict is not 'ok', the body is an interstitial rather than the article and must not be summarised as though it were the content.

NameRequiredDescriptionDefault
urlYes
max_charsNo
use_sessionNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Clearly discloses that the response includes a verdict line that must be checked, and warns that a non-'ok' verdict means the body is an interstitial and must not be summarized as content. This is valuable behavioral context beyond the readOnlyHint annotation, and it directly prevents a likely misuse.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized for the complexity, with the core purpose front-loaded and usage conditions clearly structured. It earns its length by giving concrete error cases and a safety caveat; it is not overly verbose, though it could be slightly tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and the fact that there is an output schema, the description is complete for an agent to call it correctly: it knows when to use it, what to expect in the response, and how to avoid misinterpreting interstitials. No critical operational detail is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate; it does not mention individual parameters like max_chars or use_session, but the core parameter 'url' is fully implied ('Fetch a web page...'). The behavioral verdict warning adds context that indirectly helps the agent interpret the output, but explicit parameter-level guidance is still missing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action ('Fetch a web page over the user's own internet connection') and an explicit resource ('user's own... URL'), and it differentiates itself by emphasizing the local-network/user-machine execution path versus the built-in fetcher. It is unambiguous about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides extensive when-to-use criteria: use only after built-in fetch fails with errors, interstitials, geo-restrictions, etc., and explicitly says DO NOT use as first attempt for ordinary pages. This is exactly the kind of conditional routing guidance an agent needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.3.0
    • First observedfetch_url_locally

TDQS

A4.6/5.0

Scored across 1 tool

Disambiguation5/5

There is only one tool, so there is no possibility of confusing it with another tool. Its purpose is clearly described and scoped.

Naming Consistency5/5

The single tool name follows a clear, descriptive snake_case convention. With only one tool, there are no inconsistent patterns to evaluate.

Tool Count3/5

A single tool is borderline for a server, but it may be justified for a narrowly-focused fallback fetch utility. It feels thin compared to broader MCP servers, but not absurdly so.

Completeness4/5

The tool completely covers its stated purpose of fetching pages locally and returning readable text. Minor gaps exist around request customization or response metadata, but no core workflow dead ends are apparent.

Maintenance

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude to browse the web and make GET/POST/PUT requests with a real Chrome TLS/HTTP2 fingerprint to avoid anti-bot detection, supporting persistent cookie sessions and optional proxies.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Provides a direct bridge between Claude and an authenticated Chrome session, enabling fetch requests with session cookies and JavaScript execution within live web pages.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables Claude and other MCP clients to read, extract, crawl, and export data from open browser tabs and specified URLs locally, including logged-in sessions, structured page data, contacts, images, sitemaps, and Shopify catalogues.
    MIT