Skip to main content
Glama

local-web-mcp

Version 0.3.0 · AGPL-3.0

Dieses Werkzeug wurde mit Unterstützung durch KI entwickelt, wurde aber vor dem Upload von einem Menschen geprüft.

Ein MCP-Server, der Claude einen Fallback-Web-Fetcher bereitstellt, der auf deinem eigenen Rechner läuft. Wenn der eingebaute Fetcher blockiert ist, versucht dieser es von deiner IP, deiner Verbindung und optional deiner angemeldeten Sitzung aus.

Ein Werkzeug: fetch_url_locally.

Das Problem, das es löst

Gehostete Fetcher laufen aus IP-Bereichen von Rechenzentren, die viele Websites grundsätzlich ablehnen. Ein lokaler stdio-MCP-Server tut das nicht: Der Client startet den Prozess auf deinem Rechner, also stammen die Anfragen aus deiner normalen Verbindung.

Verifiziert funktionierend auf Websites, die der gehostete Fetcher nicht lesen konnte, darunter CNBC, Politiken und Bloomberg.

Related MCP server: Proxy Browser MCP Server

Was es nicht ändert

Einen klaren Hinweis wert, weil die Rahmung zu Übertreibungen einlädt.

  • Die Modellinferenz läuft weiterhin auf den Servern von Anthropic.

  • Der abgerufene Seitentext wird weiterhin als Werkzeugausgabe an das Modell gesendet. Alles, was über eine angemeldete Sitzung gelesen wird, geht damit mit.

  • Es ändert, wer mit der Website spricht, nicht wo das Modell läuft.

Die harte Grenze

Kann die Seite ohne Ausführung von JavaScript gelesen werden?

Wenn ja, erledigt dieses Werkzeug das. Wenn nein, führt weder auf Header-, TLS- noch Cookie-Ebene etwas dorthin, und auch noch so viel User-Agent-Feintuning hilft nicht. Websites mit DataDome, Cloudflare Turnstile, PerimeterX und Ähnlichem liefern eine Herausforderung aus, die ausgeführt werden muss, um sie zu bestehen. Verwende dafür ein browserbasiertes Werkzeug oder öffne die Seite selbst.

Das ist eine Grenze, die man kennen sollte, kein Fehler, den es zu beheben gilt.

Bewertungen

Jede Antwort ist gekennzeichnet. Der gefährliche Fall ist kein offensichtlicher 403, sondern eine 200, die nicht die Seite ist: ein Bot-Zwischenfenster, eine Zustimmungsmauer, eine leere client-gerenderte Hülle. Diese werden zusammengefasst, als wären sie der Artikel.

Bewertung

Bedeutung

Was zu tun ist

ok

Echte Inhalte

Verwenden

challenge

Botschutz erkannt

Browser erforderlich, anhalten

blocked

Direkt abgelehnt (403), meist Bot-Erkennung

Browser erforderlich, anhalten

js_required

Client-gerenderte Hülle, ohne JS keine Inhalte

Browser erforderlich, anhalten

login_required

401, Anmeldewand oder Bezahlwand

Cookies könnten helfen

http_error

Jeder andere Nicht-2xx-Status (404, 429, 5xx)

Nur bei 429/5xx später erneut versuchen

empty

Unter 200 Zeichen extrahiert

Fehlgeschlagenes Lesen, keine leere Seite

Alles andere als ok bringt eine ausdrückliche Warnung an, die dem Modell sagt, den Textkörper nicht als Inhalt zu behandeln.

Der Beweis aus dem Textkörper hat Vorrang vor dem Statuscode. Ein Verlag, der einen Artikel hinter einer Bezahlschranke als HTTP 403 ausliefert, wird als login_required gemeldet, nicht als blocked, weil der nützliche Rat dort ist, Cookies zu exportieren, statt zu einem Browser zu greifen.

Die Erkennung zielt auf Anbieter-Infrastruktur statt auf Formulierungen: Herausforderungsseiten sind lokalisiert, also ist captcha-delivery.com ein zuverlässiges Signal, wo „Verifying your device" es nicht ist. Anbieter-Cookies in Antwort-Headern zählen als Beleg, wenn sie mit einem Verweigerungsstatus einhergehen.

Das Werkzeug

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

Parameter

Typ

Standard

Zweck

url

string

erforderlich

Die Seite, die abgerufen werden soll. Nur http und https

max_chars

integer

20000

Obergrenze für zurückgegebenen Text, begrenzt auf 200000. Kürzung wird im Header gemeldet

use_session

boolean

true

Cookies senden. false übergeben, um zu testen, ob eine Seite wirklich öffentlich ist

Die Antwort besteht aus einem kurzen Header, gefolgt vom extrahierten Text:

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

The article text...

Session: erscheint nur, wenn tatsächlich Cookies geladen wurden, die für diesen Host gelten. Eine andere Bewertung als ok fügt eine WARNING:-Zeile hinzu, die dem Modell sagt, den Textkörper nicht als Inhalt zu behandeln.

Fehler kommen als Fehlermeldung zurück, die die Ursache benennt, zum Beispiel [blocked_host] Host '192.168.1.5' resolves to a private or internal address (deutsch: Host '192.168.1.5' löst zu einer privaten oder internen Adresse auf). Codes: invalid_url, blocked_scheme, blocked_host, dns_failure, timeout, too_many_redirects, upstream_error, invalid_argument.

Voraussetzungen

  • Python 3.11+ (verwendet asyncio.timeout). Mit uv musst du es nicht selbst installieren; uv holt eine geeignete Python-Interpretation

  • Claude Desktop oder Claude Code. Stdio-Server funktionieren nicht im Browser oder in der mobilen App; diese benötigen einen öffentlich erreichbaren HTTPS-Endpunkt.

Installation

Mit uv, das selbst ein geeignetes Python und die Abhängigkeiten holt:

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

Führe das einmal in einem Terminal aus, bevor du den Server registrierst. Der erste Lauf löst die Umgebung auf und baut sie auf, was lange genug dauert, dass ein Client, der den Server kalt startet, aufgeben und den Server als fehlgeschlagen melden könnte, obwohl die Konfiguration korrekt ist.

Es gibt Starting local-web aus und wartet dann auf einen Client auf stdin, was wie ein funktionierender Server aussieht. Sobald du diese Zeile siehst, ist die Umgebung gebaut: Drücke Ctrl+C und mach weiter.

Oder mit einer einfachen virtuellen Umgebung:

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

Bei Claude Desktop registrieren

Füge zu claude_desktop_config.json hinzu (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"
      ]
    }
  }
}

Wenn uv nicht im PATH liegt, den der Client sieht, verwende den absoluten Pfad als command. Das Pendant mit virtueller Umgebung ist:

{
  "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

Konfiguration

Alles optional. Jede Einstellung hat einen funktionierenden Standardwert.

Variable

Standard

Zweck

LOCALWEB_COOKIE_FILE

nicht gesetzt

Pfad zu einem Cookie-Jar

LOCALWEB_COOKIE_DOMAINS

nicht gesetzt

Domains, für die der Jar verwendet werden darf. Immer setzen, wenn du eine Cookie-Datei setzt

LOCALWEB_ALLOW_PRIVATE

false

Private, Loopback- und Link-Local-Ziele erlauben

LOCALWEB_ALLOWLIST

leer

Hostnamen, die von der IP-Prüfung ausgenommen sind

LOCALWEB_USER_AGENT

Chrome-UA

Wird bei jeder Anfrage gesendet

LOCALWEB_ACCEPT_LANGUAGE

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

Spracheinstellung. Websites nutzen sie, um eine Sprache und manchmal eine Regionaledition zu wählen

LOCALWEB_CONNECT_TIMEOUT

5

Sekunden

LOCALWEB_READ_TIMEOUT

20

Sekunden

LOCALWEB_TOTAL_TIMEOUT

40

Harte Obergrenze pro Aufruf

LOCALWEB_MAX_BYTES

3000000

Obergrenze für den Antworttextkörper

LOCALWEB_MAX_REDIRECTS

5

Redirect-Sprünge, gemeinsam mit Meta-Refreshes

Der Standard-Accept-Language fragt zuerst Dänisch an. Das ist eine bewusste Standardwahl statt einer neutralen, also setze LOCALWEB_ACCEPT_LANGUAGE, wenn du Englisch oder etwas anderes möchtest:

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

Sitzungs-Cookies

Weise LOCALWEB_COOKIE_FILE auf einen Export aus einer Browser-Erweiterung. Der Lader akzeptiert Netscape-cookies.txt-Dateien mit beliebigem Header oder ohne Header sowie JSON-Exporte der gängigen Erweiterungen. Siehe cookies.txt.example.

Setze immer LOCALWEB_COOKIE_DOMAINS. Ohne diese Angabe ist der gesamte Jar aktiv und jeder Abruf kann eine unzusammenhängende Sitzung mitführen. Mit ihr werden alle Cookies außerhalb dieser Domains bereits beim Laden verworfen, bevor der Jar einen Client erreicht. Der Abgleich umfasst Subdomains (example.com deckt www.example.com ab), aber keine Ähnlichkeiten (evil-example.com).

Drei Dinge, die du im Hinterkopf behalten solltest:

  1. Inhalte, die über deine Sitzung gelesen werden, werden als Werkzeugausgabe an das Modell gesendet.

  2. Eine Cookie-Datei ist eine Zugangsdaten-Datei. chmod 600, und sie ist hier gitignored.

  3. Cookies laufen ab. Wenn eine zuvor funktionierende Quelle plötzlich login_required liefert, ist das meist ein veralteter Export und kein verlorener Zugang.

Übergib use_session=false, um zu prüfen, ob eine Seite wirklich öffentlich ist.

Ein lokales Netzwerk erreichen

Private Adressen sind standardmäßig blockiert, und das ist beabsichtigt. Das Modell wählt URLs teilweise aus Text aus, den es gerade gelesen hat, also kann eine abgerufene Seite versuchen, es auf 192.168.1.1 zu lenken. Die Blockliste bedeutet, dass eine Prompt-Injection im Seiteninhalt dies nicht in einen Netzwerkscanner verwandeln kann.

Bevorzuge eine enge Allowlist gegenüber dem pauschalen Schalter:

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

Sicherheit

  • Schema auf http und https beschränkt; URLs mit Zugangsdaten werden abgelehnt

  • Hostname wird aufgelöst und jede zurückgegebene Adresse vor der Anfrage validiert

  • IPv4-Adressen in IPv6-Schreibweise (::ffff:10.0.0.1) werden vor der Prüfung entpackt

  • Cloud-Metadaten-Endpunkte sind bedingungslos blockiert: Der Hostname wird vor sowohl der Allowlist als auch ALLOW_PRIVATE aufgelöst, also kann keines von beiden sie öffnen

  • Redirects und Meta-Refreshes werden manuell verfolgt und bei jedem Sprung neu validiert

  • Cookie-Anzahlen werden protokolliert, niemals Namen, Werte oder Domains

Bekannte Einschränkungen

  • Kein JavaScript. Die harte Grenze oben.

  • DNS-Rebinding. Der Hostname wird zur Validierung aufgelöst und dann beim Verbinden erneut aufgelöst. Um diese Lücke zu schließen, muss die Verbindung an die validierte IP gebunden werden. Sinnvoll, bevor man ALLOW_PRIVATE in einem unsicheren Netzwerk aktiviert.

  • Die Erkennung von Herausforderungen ist signaturbasiert und wird abweichen, wenn Anbieter ihr Markup ändern. Führe inspect_response.py aus, wenn eine Bewertung falsch aussieht.

  • Die HTML-zu-Text-Extraktion ist ohne Abhängigkeiten und grob. trafilatura wäre für ernsthafte Artikelextraktion deutlich besser.

Dateien

Datei

Zweck

local_web_mcp.py

Der Server

cookies.py

Nachsichtiger Cookie-Lader. Erforderlich, wird vom Server importiert

inspect_response.py

Diagnose: gibt aus, was der Fetcher tatsächlich empfängt

unit_test.py

Bewertungen, Zielvalidierung, Cookie-Laden und -Abgrenzung

smoke_test.py

Blockierte Ziele und ein Live-Abruf über stdio

cookies.txt.example

Kommentierte Vorlage für einen Cookie-Jar

pyproject.toml

Paketmetadaten und der Einstiegspunkt local-web-mcp

uv.lock

Festgeschriebene Abhängigkeitsversionen für reproduzierbare Installationen

requirements.txt

Laufzeitabhängigkeiten für den Weg mit einfacher venv

.gitignore

Schließt venv, Caches und jede Cookie-Datei aus

LICENSE

Vollständiger AGPL-3.0-Text

Eine falsche Bewertung diagnostizieren

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

Gibt den Status, die interessanten Header, den Anfang des Textkörpers aus und führt dann die eigene Erkennung des Servers dagegen aus. Prüfe das immer, bevor du Erkennungslogik änderst. Ein Browser und dieser Fetcher bekommen häufig völlig unterschiedliche Antworten ausgeliefert. Was du auf dem Bildschirm siehst, ist also kein Beleg dafür, was der Fetcher empfangen hat.

Tests

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

unit_test.py läuft offline und beendet sich bei einem Fehler mit einem Exit-Code ungleich null, sodass es als Pre-Commit-Gate dient. smoke_test.py steuert den Server über stdio und sendet eine Live-Anfrage; es benötigt also eine Netzwerkverbindung. Führen Sie beide im Stammverzeichnis des Repositorys aus.

Beim plain-venv-Weg ersetzen Sie uv run python durch .venv/bin/python.

Lizenz

Copyright (C) 2026 David Lindholm.

GNU Affero General Public License v3.0 oder neuer. Siehe LICENSE.

Dieses Programm wird in der Hoffnung weitergegeben, dass es nützlich sein wird, aber OHNE JEGLICHE GARANTIE; selbst ohne die stillschweigende Garantie der MARKTGÄNGIGKEIT oder der EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.

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