blowsh-mcp
blowsh-mcp
Сервер Model Context Protocol для терминального браузера с поддержкой JS на базе Browsh
Что такое blowsh-mcp?
blowsh-mcp — это сервер Model Context Protocol (MCP), который открывает возможности Browsh — полностью поддерживающего JavaScript терминального браузера — для любого AI-агента, IDE-агента или MCP-клиента. Этот проект позволяет вашему ИИ получать и отображать любые современные веб-страницы, в том числе требующие JavaScript, и получать результат в виде легко разбираемого обычного текста, HTML или Markdown.
Мнемоника: «blowsh» = MCP-сервер на базе Browsh.
Related MCP server: openmcp
Ключевые возможности
Инструмент fetch_web: единый инструмент для извлечения читаемого обычного текста, HTML или Markdown (после полного рендеринга JS). Поддерживает извлечение по CSS
selector, ограничение выводаmax_charsи опросwait_msдля ожидания завершения JS.Инструмент search_web: поиск страниц через отрендеренную поисковую систему (DuckDuckGo HTML с запасным вариантом Bing) — ранжированные результаты с URL и сниппетами.
Инструмент extract_links: выводит список гиперссылок (текст + абсолютный URL) с любой JS-отрендеренной страницы для последующей навигации.
Инструмент fetch_web_batch: загрузка до 10 URL за один вызов с изоляцией ошибок по каждому URL.
Защита SSRF: отклоняет запросы к loopback, частным, link-local или зарезервированным адресам (с резолвингом DNS), защищая серверный браузер.
AI-оптимизированная документация инструментов: входные и выходные данные, а также иллюстрированные примеры использования, предназначенные для бесшовной автоматизации агентов. Инструменты генерируют структурированные ошибки с HTTP-статус кодами (
isErrorв ответах MCP).Надёжное управление Browsh: запускает Browsh один раз, поддерживает его работу, переиспользует лёгкий по RAM/CPU синглтон, корректно завершает работу при выходе.
Кэш рендеринга в памяти с TTL: повторные запросы обслуживаются мгновенно без повторного рендеринга.
Разработан для PaaS, облака, локальных AI-инструментов и IDE-агентов.
Ссылки
Browsh CLI Browser — Движок рендеринга.
Firefox — Требуется в качестве бэкенда для Browsh.
Model Context Protocol (MCP) Specification — Протокол взаимодействия агента и сервера.
Как это работает
AI/агент отправляет MCP-запрос:
fetch_web(один URL),search_web(запрос),extract_links(URL) илиfetch_web_batch(до 10 URL).blowsh-mcp запускает Browsh в режиме HTTP-сервера (при первом использовании) и переиспользует его для всех последующих вызовов.
blowsh-mcp запрашивает исходный вывод от Browsh, используя
X-Browsh-Raw-Mode: PLAIN(для текста),DOM(для HTML), или получает HTML и затем преобразует его в Markdown.Страница (после полного выполнения JS) возвращается как терминальный обычный текст, насыщенный HTML DOM или чистый Markdown — AI/агенты выбирают тип вывода в соответствии с дальнейшей обработкой.
Результаты кэшируются в памяти (TTL), поэтому повторные запросы выполняются мгновенно; каждый запрос проверяется на SSRF перед отправкой в браузер.
Быстрый старт (Docker — готовый образ)
Образ публикуется в GitHub Container Registry и автоматически пересобирается при каждом пуше в main через GitHub Actions — не требуется устанавливать Firefox/Browsh/html2markdown на хосте:
docker pull ghcr.io/mokhtarabadi/blowsh-mcp:latest
docker run --rm -i ghcr.io/mokhtarabadi/blowsh-mcp:latestФлаг
-iобязателен: MCP-сервер общается по JSON-RPC через stdin/stdout. Оставьте его интерактивным и передавайте запросы через конвейер или укажите ваш MCP-клиент на него (см. Конфигурация AI-клиента ниже).
Пример использования
Из Claude, Cursor или любого MCP-совместимого агента:
{
"tool": "search_web",
"params": { "query": "bitcoin price today", "max_results": 5 }
}
// → Ranked results with URLs + snippets → feed top URL to fetch_web
{
"tool": "fetch_web",
"params": { "url": "https://coindesk.com/price/bitcoin/", "type": "plain" }
}
// → Returns readable plain text (live price as text table, etc)
{
"tool": "fetch_web",
"params": { "url": "https://coindesk.com/price/bitcoin/", "type": "markdown", "selector": "main", "wait_ms": 3000 }
}
// → Markdown of <main> only, after JS settles ("# Bitcoin Price\n\n| Time | Price | ...")
{
"tool": "extract_links",
"params": { "url": "https://example.com", "limit": 20 }
}
// → [{"text": "Learn more", "url": "https://iana.org/domains/example"}, ...]
{
"tool": "fetch_web_batch",
"params": { "urls": ["https://a.com", "https://b.com"], "type": "markdown" }
}
// → Per-URL results; a failing page never fails the batchAI получает:
С
type: plain: чистый читаемый текст (таблицы, списки, основное содержимое; идеально для NLP/суммаризации или приёма в терминал).С
type: html: полная HTML-разметка после выполнения всего JavaScript. Используйте для разбора элементов, построения графа ссылок, сложного скрейпинга и т.д.С
type: markdown: чистая Markdown-версия — лучше всего подходит для контекстных блоков LLM, семантических конвейеров и AI-ориентированного потребления/рабочих процессов.Ошибки структурированы: MCP-ответы устанавливают
isError: trueс сообщениемFetchError, включающим HTTP-статус, когда он доступен.
Структура проекта
src/server.ts— MCP-сервер, предоставляющий инструменты.src/browshManager.ts— Запуск, мониторинг и завершение Browsh.src/tools/fetchWeb.ts— Реализация инструмента fetchWeb (plain, html, markdown; selector/max_chars/wait_ms).src/tools/searchWeb.ts— search_web (парсер DuckDuckGo HTML + запасной вариант Bing).src/tools/extractLinks.ts— extract_links (гиперссылки из отрендеренного DOM).src/tools/fetchWebBatch.ts— fetch_web_batch (несколько URL, изоляция ошибок по каждому URL).src/tools/html2markdownManager.ts— Обёртка для CLI html2markdown.src/ssrf.ts— Защита SSRF (блокирует частные/loopback/зарезервированные цели).src/cache.ts— Кэш рендеринга в памяти с TTL.src/extract.ts— Извлечение основного содержимого, вспомогательные функции для selector, усечение.src/errors.ts—FetchError+ форматирование сообщений.README.md— Этот файл.Dockerfile— Многоступенчатый контейнер (собирает TS, включает Firefox, Browsh, html2markdown)..github/workflows/docker-publish.yml— CI/CD: собирает и публикует образ в ghcr.io при пушах вmain/v*..env— Переопределения конфигурации. Все опции см. в.env.example.
Установка
Требования:
Node.js >= 20.18
Firefox установлен и доступен в PATH
Browsh CLI установлен и доступен в PATH
html2markdown CLI установлен и доступен в PATH
На Debian/Ubuntu установите с помощью:
wget -O /tmp/html2markdown.deb "https://github.com/JohannesKaufmann/html-to-markdown/releases/download/v2.5.2/html2markdown_2.5.2_linux_amd64.deb" sudo apt-get install -y /tmp/html2markdown.deb rm /tmp/html2markdown.debИли используйте готовый бинарный файл для вашей ОС со страницы релизов.
Предпочитаете Docker? Полностью пропустите установку на хосте — многоступенчатый образ включает Firefox, Browsh и html2markdown. Самый быстрый путь — опубликованный образ (
ghcr.io/mokhtarabadi/blowsh-mcp:latest, см. Быстрый старт); чтобы собрать его самостоятельно:docker build -t blowsh-mcp:latest . docker run --rm -i blowsh-mcp:latest
git clone https://github.com/mokhtarabadi/blowsh-mcp.git
cd blowsh-mcp
npm install
npm run buildЗапуск MCP-сервера
После сборки запустите сервер, используя:
node dist/server.jsЗамените dist/server.js на правильный путь, если вывод вашей сборки отличается.
При необходимости создайте файл .env для конфигурации. Например:
MCP_TRANSPORT=stdio
BROWSH_FIREFOX_PATH=/usr/bin/firefox-esr
HTML2MARKDOWN_PATH=html2markdown
CACHE_TTL_MS=300000
BROWSH_REQUEST_TIMEOUT_MS=30000
ALLOW_PRIVATE_URLS=false
NODE_ENV=productionBROWSH_FIREFOX_PATHпозволяет настроить исполняемый файл Firefox, используемый Browsh во время headless/HTTP-работы.HTML2MARKDOWN_PATHпозволяет указать свой путь к бинарному файлу html2markdown (по умолчанию:html2markdownв PATH).CACHE_TTL_MS,BROWSH_REQUEST_TIMEOUT_MSиALLOW_PRIVATE_URLSнастраивают соответственно кэш рендеринга, тайм-аут запроса и защиту SSRF.HTTP-порт/хост Browsh не настраиваются.
Документация проекта
Файл | Аудитория | Назначение |
| Агенты | Правила работы, ограничения, жизненный цикл задач |
| Все | Язык дизайна ответов/вывода MCP |
| Разработчики | Обзор системы, соединение компонентов |
| Разработчики | Схемы ввода/вывода инструментов и модель ошибок |
| Разработчики | Стандарт DateTime, рекомендации SOLID |
| Все | История версий (Keep a Changelog) |
| Команда | Файлы задач Kanban (backlog → archive) |
Этот README — пользовательская точка входа; правила для агентов находятся в AGENTS.md и обязательны к прочтению перед любой реализацией.
API инструментов
Имя | Параметры | AI Вариант использования/Описание |
fetch_web |
| Загружает одну страницу после JS-рендеринга как текст/HTML/Markdown. |
search_web |
| Выполняет поиск в Интернете (DuckDuckGo HTML + Bing, рендеринг параллельно) и возвращает |
extract_links |
| Возвращает все гиперссылки ( |
fetch_web_batch |
| Загружает до 10 URL за один вызов (с учётом кэша). Возвращает по каждому URL |
Возвращает
type: plain: терминальный, выполненный через JS читаемый текст (или строка ошибки).type: html: строка HTML-разметки после JS (или строка ошибки). Сselector— только HTML соответствующего элемента.type: markdown: преобразование основного содержимого или выбранного элемента в Markdown (или строка ошибки). Ссылки, заголовки, списки и структура страницы сохраняются для AI-ориентированного контекста.type: pdf: извлечённый обычный текст из PDF-документа (через pdftotext, лимит 20 МБ).Ошибки структурированы: MCP-ответ с
isError: trueи сообщениемFetchError, включающим HTTP-статус, когда он известен (никогда не бывает молчаливой пустой строки).
Переменные окружения
Задайте их через .env (загружается автоматически) или через окружение:
Переменная | По умолчанию | Описание |
|
| Бинарный файл Firefox, используемый Browsh (например, |
|
| Путь к бинарному файлу html2markdown. |
|
| Таймаут запроса на рендеринг (мс). |
|
| Максимальный размер PDF-файла в байтах для |
|
| Количество запросов, после которого процесс браузера перезапускается. |
|
| Время простоя в мс до завершения процесса браузера (10 мин). |
|
| TTL кэша рендеринга в памяти (мс). |
|
| Установите |
|
| Тип транспорта (реализован только |
|
| Среда Node.js. |
Выбор инструментов с помощью ИИ
Начните с
search_web: Чтобы обнаружить страницы, выполните запрос и выберите лучшие URL-адреса результатов; затем загрузите их.Используйте
fetch_webдля отдельных страниц:plain— когда нужен быстрый читаемый вывод для суммаризации/классификации;html— для разбора элементов, ссылок или таблиц;markdown— для удобных для LLM фрагментов контекста. Добавляйтеselector/max_chars/wait_ms, чтобы экономить токены и получать стабильный релевантный контент.Используйте
extract_linksперед глубоким обходом: Следуйте по навигации без лишних затрат, вместо загрузки полных DOM-деревьев.Используйте
fetch_web_batchдля нескольких источников: Один вызов вместо N обращений; сбои изолированы для каждого URL.
Обработка ошибок:
Инструменты выбрасывают FetchError, а MCP возвращает isError: true с практическим сообщением — недопустимые протоколы, блокировки SSRF, несовпадающие селекторы, коды состояния HTTP и ошибки рендеринга никогда не остаются незамеченными.
Протокол MCP: настройка ИИ-клиента
Перед настройкой вашего ИИ-клиента (Claude, Cursor и т.д.) необходимо
Установить зависимости:
npm installСобрать проект:
npm run buildЗапустить MCP-сервер из скомпилированного вывода:
node dist/server.js
Пример конфигурации для Claude Desktop или Cursor:
{
"mcpServers": {
"blowsh": {
"command": "node",
"args": ["dist/server.js"],
"env": {}
}
}
}Пример конфигурации для opencode (файл проекта opencode.json):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"blowsh": {
"type": "local",
"command": ["docker", "run", "--rm", "-i", "ghcr.io/mokhtarabadi/blowsh-mcp:latest"],
"enabled": true,
"timeout": 120000
}
},
"permission": { "blowsh_*": "allow" }
}Docker-вариант не требует бинарных файлов на хосте; образ включает Firefox, Browsh и html2markdown. Перезапустите opencode после сохранения (конфигурация загружается один раз при запуске).
Плавное завершение работы
blowsh-mcp перехватывает SIGINT/SIGTERM и гарантирует чистое завершение Browsh — без осиротевших процессов браузера.
Безопасность и рекомендации
Сервер запускает Browsh локально и выполняет запросы через HTTP localhost.
Защита SSRF: По умолчанию
fetch_web/search_web/extract_links/fetch_web_batchотказываются от URL-адресов, которые разрешаются в loopback, частные, link-local или зарезервированные IP-диапазоны (проверяется через DNS). УстановитеALLOW_PRIVATE_URLS=true, чтобы отключить — не рекомендуется.Нет публичного доступа, если явно не настроен MCP HTTP/streamable сервер.
Никогда не открывайте порты в открытый веб без межсетевого экрана.
Используйте переменные окружения для секретов/конфигурации.
Расширение
Добавляйте новые инструменты в src/tools/, экспортируйте их в src/server.ts и документируйте.
ИИ-клиенты автоматически найдут docstrings.
Устранение неполадок
Если fetchPlain возвращает 404 или не удаётся отрендерить JS: проверьте, что Firefox и Browsh установлены и находятся в PATH.
Если Firefox не найден или не запускается, установите
BROWSH_FIREFOX_PATHв.env, указав полный путь до вашей установки Firefox.Порт/хост Browsh фиксированы — нет ни переменной окружения, ни параметра CLI для их изменения.
Для максимальной безопасности запускайте в контейнере.
Лицензия
MIT
Автор: Mohammad Reza Mokhtarabadi mmokhtarabadi@gmail.com
Available Tools
1 toolfetch_webFetch Web (plain, html, markdown)A
Fetch a web page and return its content as plain text, HTML, or Markdown. Uses a JS-capable browser for dynamic sites.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The HTTP/HTTPS web URL to fetch | |
| type | Yes | The output type: plain, html, or markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden for behavioral traits. It discloses the use of a JS-capable browser, which is critical for understanding behavior with dynamic sites. It does not mention rate limits or error handling, but the core behavioral trait is well covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loading the main purpose and adding the browser capability as a key differentiator. Every sentence earns its place without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 2 simple parameters, no output schema, and no annotations, the description is sufficient. It covers the purpose, output types, and a notable behavior (JS browser). Minor missing details like response size limits or timeout are not critical for a basic fetch tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with both parameters well described. The description adds 'plain text, HTML, or Markdown' but that is a restatement of the enum values. No additional nuance is provided beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (fetch a web page) and the resource (web page content), and specifies three output types (plain, HTML, Markdown). It distinguishes the tool by mentioning JS-capable browser for dynamic sites, which sets it apart from simple fetchers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool vs alternatives or when not to use it. Given no sibling tools are listed, it is minimally adequate but lacks context like 'use for public pages only' or 'prefer for dynamic content'.
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 tool update
v1.0.0- First observed
fetch_web
TDQS
Scored across 1 tool
With only one tool, there is no possibility of ambiguity between tools. The tool's purpose is clear and distinct.
The single tool name 'fetch_web' follows a clear verb_noun pattern. With only one tool, there is no inconsistency to evaluate.
A single tool is borderline for a server. While it serves a specific purpose, it feels thin compared to typical MCP servers that offer multiple related operations.
The tool provides core web fetching functionality with output format options. A minor gap might be the lack of custom headers or request methods, but agents can work around this for most use cases.
Maintenance
Related MCP Connectors
- CrawioOAuthcom.crawio
Web pages as Markdown, text or HTML, plus Google Maps places and reviews, for AI agents.
Unblocking and fresh web data for agents: URL to Markdown, YouTube, Maps, Amazon, jobs. Pay per call
Web scraping for AI agents. Converts URLs to clean, LLM-ready Markdown with anti-bot bypass.
Headless browser primitives for AI agents when sites need real JS rendering.
Related MCP Servers
AlicenseAqualityFmaintenanceA Model Context Protocol server that enables AI agents to fetch live web content with JavaScript rendering, proxy rotation, and anti-bot evasion.979 npm58MIT- AlicenseNot gradedqualityDmaintenanceEnables AI agents to automate web tasks such as browsing, clicking, typing, and taking screenshots via the Model Context Protocol.1MIT

Browseagent MCPofficial
AlicenseAqualityDmaintenanceEnables AI agents to control web browsers through the Model Context Protocol, supporting navigation, clicking, typing, and screenshots.127 npm1MIT- AlicenseAqualityDmaintenanceEnables AI agents to fetch any web page as clean markdown or screenshot it, turning URLs into LLM-ready context.27 npmMIT