Skip to main content
Glama

local-web-mcp

Версия 0.3.0 · AGPL-3.0

Этот инструмент разработан при поддержке ИИ, но перед публикацией он был проверен человеком.

MCP-сервер, который даёт Claude запасной веб-загрузчик, работающий на вашей собственной машине. Когда встроенный загрузчик заблокирован, этот попробует выполнить запрос с вашего IP-адреса, через ваше соединение и, опционально, с вашей авторизованной сессией.

Один инструмент: fetch_url_locally.

Какую проблему он решает

Размещённые загрузчики работают с IP-диапазонов дата-центров, которые многие сайты отклоняют сразу. Локальный stdio-MCP-сервер — нет: клиент запускает процесс на вашей машине, поэтому запросы исходят из вашего обычного подключения.

Проверено и работает на сайтах, которые размещённый загрузчик не мог прочитать, включая CNBC, Politiken и Bloomberg.

Related MCP server: Proxy Browser MCP Server

Что он не меняет

Это стоит сказать прямо, потому что такая постановка вопроса провоцирует преувеличения.

  • Вывод модели по-прежнему выполняется на серверах Anthropic.

  • Текст загруженной страницы по-прежнему отправляется модели как выходные данные инструмента. Всё, что прочитано через авторизованную сессию, уходит вместе с ним.

  • Меняется кто общается с сайтом, а не где выполняется модель.

Жёсткая граница

Можно ли прочитать страницу без выполнения JavaScript?

Если да, этот инструмент справится. Если нет, ничто на уровне заголовков, TLS или cookie туда не проберётся, и никакая настройка User-Agent не поможет. Сайты, использующие DataDome, Cloudflare Turnstile, PerimeterX и подобные, выдают проверку (challenge), которую нужно выполнить, чтобы пройти. Для таких используйте инструмент на основе браузера или откройте страницу сами.

Это граница, о которой нужно знать, а не ошибка, которую нужно исправлять.

Вердикты

Каждый ответ помечается. Опасный случай — не явная ошибка 403, а 200, который не является страницей: промежуточная страница для ботов, баннер согласия на обработку данных, пустая оболочка, отрисованная на клиенте. Они попадают в сводку так, будто это статья.

Вердикт

Значение

Что делать

ok

Реальный контент

Используйте

challenge

Обнаружена защита от ботов

Нужен браузер, остановитесь

blocked

Полный отказ (403), обычно обнаружение ботов

Нужен браузер, остановитесь

js_required

Оболочка, отрисованная на клиенте, без JS контента нет

Нужен браузер, остановитесь

login_required

401, логин-стена или платный барьер

Могут помочь cookie

http_error

Любой другой статус не 2xx (404, 429, 5xx)

Повторите позже только для 429/5xx

empty

Извлечено менее 200 символов

Сбой чтения, а не пустая страница

Всё, что не является ok, сопровождается явным предупреждением, которое сообщает модели не рассматривать тело ответа как контент.

Доказательства из тела ответа важнее кода статуса. Издатель, который отдаёт статью за платным барьером с HTTP 403, будет помечен как login_required, а не blocked, потому что в этом случае полезный совет — экспортировать cookie, а не тянуться за браузером.

Детектирование опирается на инфраструктуру вендора, а не на формулировки: страницы проверки локализованы, поэтому captcha-delivery.com — надёжный сигнал там, где «проверка вашего устройства» — нет. Cookie вендора в заголовках ответа считаются доказательством в сочетании со статусом отказа.

Инструмент

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

Параметр

Тип

По умолчанию

Назначение

url

string

обязательно

Страница для загрузки. Только http и https

max_chars

integer

20000

Ограничение возвращаемого текста, не более 200000. Об усечении сообщается в заголовке

use_session

boolean

true

Отправлять cookie. Передайте false, чтобы проверить, действительно ли страница публичная

Ответ состоит из короткого заголовка и извлечённого текста:

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

The article text...

Session: появляется только тогда, когда cookie действительно загружены и ограничены этим хостом. Вердикт, отличный от ok, добавляет строку WARNING: с указанием модели не рассматривать тело ответа как контент.

Сбои возвращаются как ошибка с указанием причины, например [blocked_host] Host '192.168.1.5' resolves to a private or internal address. Коды: invalid_url, blocked_scheme, blocked_host, dns_failure, timeout, too_many_redirects, upstream_error, invalid_argument.

Требования

  • Python 3.11+ (использует asyncio.timeout). С uv вам не нужно устанавливать его самостоятельно; uv подберёт подходящий интерпретатор

  • Claude Desktop или Claude Code. Stdio-серверы не работают в браузере или мобильном приложении, которым требуется публично доступный HTTPS-эндпоинт.

Установка

С помощью uv, который сам подбирает подходящий Python и зависимости:

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

Выполните это один раз в терминале перед регистрацией сервера. Первый запуск разрешает зависимости и создаёт окружение; это занимает достаточно много времени, поэтому клиент, запускающий его без предварительной подготовки, может сдаться и сообщить об ошибке, даже если конфигурация верна.

Он выводит Starting local-web и затем ждёт клиента в stdin — так выглядит работающий сервер. Как только вы увидите эту строку, окружение создано: нажмите Ctrl+C и продолжайте.

Или с обычным виртуальным окружением:

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

Регистрация в Claude Desktop

Добавьте в 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"
      ]
    }
  }
}

Если uv отсутствует в PATH, который видит клиент, укажите его абсолютный путь как command. Эквивалент для виртуального окружения:

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

Конфигурация

Всё необязательно. У каждого параметра есть рабочий вариант по умолчанию.

Переменная

По умолчанию

Назначение

LOCALWEB_COOKIE_FILE

не задана

Путь к хранилищу cookie

LOCALWEB_COOKIE_DOMAINS

не задана

Домены, для которых может использоваться хранилище. Устанавливайте это всегда, когда задаёте файл cookie

LOCALWEB_ALLOW_PRIVATE

false

Разрешить частные, loopback и link-local адреса

LOCALWEB_ALLOWLIST

пусто

Имена хостов, исключённые из проверки IP

LOCALWEB_USER_AGENT

Chrome UA

Отправляется с каждым запросом

LOCALWEB_ACCEPT_LANGUAGE

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

Языковые предпочтения. Сайты используют их для выбора языка, а иногда и региональной версии

LOCALWEB_CONNECT_TIMEOUT

5

Секунды

LOCALWEB_READ_TIMEOUT

20

Секунды

LOCALWEB_TOTAL_TIMEOUT

40

Жёсткий предел на один вызов

LOCALWEB_MAX_BYTES

3000000

Максимальный размер тела ответа

LOCALWEB_MAX_REDIRECTS

5

Количество переходов по редиректам, общее с meta-обновлениями

Значение Accept-Language по умолчанию запрашивает сначала датский. Это осознанный выбор по умолчанию, а не нейтральный, поэтому задайте LOCALWEB_ACCEPT_LANGUAGE, если вам нужен английский или любой другой язык:

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

Укажите LOCALWEB_COOKIE_FILE на экспорт из браузерного расширения. Загрузчик принимает Netscape cookies.txt с любым заголовком или без него, а также JSON-экспорты из распространённых расширений. См. cookies.txt.example.

Всегда задавайте LOCALWEB_COOKIE_DOMAINS. Без него будет активно всё хранилище, и любой запрос может нести постороннюю сессию. С ним все cookie вне этих доменов отбрасываются при загрузке, до того как хранилище попадёт к клиенту. Совпадение охватывает поддомены (example.com покрывает www.example.com), но не похожие имена (evil-example.com).

Три вещи, о которых стоит помнить:

  1. Контент, прочитанный через вашу сессию, отправляется модели как выходные данные инструмента.

  2. Файл cookie — это файл с учётными данными. chmod 600, и он здесь в .gitignore.

  3. Cookie истекают. Источник, который раньше работал и теперь возвращает login_required, обычно означает устаревший экспорт, а не потерю доступа.

Передайте use_session=false, чтобы проверить, действительно ли страница публичная.

Доступ к локальной сети

Частные адреса заблокированы по умолчанию, и это сделано намеренно. Модель выбирает URL частично из только что прочитанного текста, поэтому загруженная страница может попытаться направить её на 192.168.1.1. Блокировка означает, что инъекция промпта в содержимое страницы не сможет превратить этот инструмент в сканер сети.

Предпочитайте узкий список разрешённых хостов безусловному переключателю:

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

Безопасность

  • Схема ограничена http и https; URL с учётными данными отклоняются

  • Имя хоста разрешается, и каждый возвращённый адрес проверяется перед запросом

  • IPv6-отображённый IPv4 (::ffff:10.0.0.1) преобразуется перед проверкой

  • Облачные metadata-эндпоинты блокируются безусловно: имя хоста разрешается до применения и списка разрешений, и ALLOW_PRIVATE, так что ни один из них не может их открыть

  • Редиректы и meta-обновления обрабатываются вручную, с повторной проверкой на каждом шаге

  • Логируется количество cookie, но никогда их имена, значения или домены

Известные ограничения

  • Нет JavaScript. Жёсткая граница, описанная выше.

  • DNS-ребиндинг. Имя хоста разрешается для проверки, а затем снова при подключении. Чтобы закрыть эту брешь, нужно привязать соединение к проверенному IP. Это стоит сделать перед включением ALLOW_PRIVATE в недоверенной сети.

  • Обнаружение проверок основано на сигнатурах и будет устаревать по мере изменения разметки вендорами. Запустите inspect_response.py, если вердикт выглядит неверным.

  • Извлечение текста из HTML не использует зависимостей и довольно грубое. Для серьёзного извлечения статей trafilatura была бы заметно лучше.

Файлы

Файл

Назначение

local_web_mcp.py

Сервер

cookies.py

Гибкий загрузчик cookie. Обязателен, импортируется сервером

inspect_response.py

Диагностика: показывает, что именно получает загрузчик

unit_test.py

Вердикты, проверка целей, загрузка и ограничение cookie

smoke_test.py

Заблокированные цели и один реальный запрос через stdio

cookies.txt.example

Аннотированный шаблон для хранилища cookie

pyproject.toml

Метаданные пакета и точка входа local-web-mcp

uv.lock

Зафиксированные версии зависимостей для воспроизводимых установок

requirements.txt

Зависимости времени выполнения для обычного виртуального окружения

.gitignore

Исключает виртуальное окружение, кэши и любые файлы cookie

LICENSE

Полный текст AGPL-3.0

Диагностика неверного вердикта

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

Выводит статус, значимые заголовки, начало тела, а затем прогоняет это через собственную детекцию сервера. Всегда проверяйте это перед изменением логики детекции. Браузеру и этому загрузчику часто отдаются совершенно разные ответы, поэтому то, что вы видите на экране, не является доказательством того, что получил инструмент.

Тесты

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

unit_test.py работает офлайн и при сбое завершается с ненулевым кодом возврата, поэтому он работает как шлюз pre-commit. smoke_test.py управляет сервером через stdio и выполняет один реальный запрос, поэтому ему требуется сетевое соединение. Запустите оба из корня репозитория.

В варианте plain-venv замените uv run python на .venv/bin/python.

Лицензия

Copyright (C) 2026 David Lindholm.

GNU Affero General Public License v3.0 или более поздняя версия. См. LICENSE.

Эта программа распространяется в надежде, что она будет полезной, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; даже без подразумеваемой гарантии КОММЕРЧЕСКОЙ ЦЕННОСТИ или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ.

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

ActivitySlowing
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