golang

MCP для Juggler на Go

  • суббота, 22 августа 2026 г. в 00:00:16
https://habr.com/ru/articles/1072740/
MCP for Juggler on GO
MCP for Juggler on GO

Вступление

ИИ-агенты уже не просто отвечают на вопросы - они действуют. Они открывают страницы, читают разметку, кликают по кнопкам, заполняют формы и делают скриншоты. А самый быстрорастущий способ дать агенту руки - это Model Context Protocol (MCP), открытый стандарт, который превращает браузер в набор инструментов, вызываемых любым ИИ-клиентом.

Браузерная половина задачи в Go уже была решена. Пакет go-https://github.com/yvv4git/go-juggler принёс стек автоматизации Camoufox/Juggler в экосистему Go в виде чистого REST-клиента. Но оставался разрыв между "я могу управлять stealth-браузером из Go" и "мой ИИ-ассистент может управлять stealth-браузером". Подключение браузерного клиента к MCP-серверу означало написание клея: определения инструментов, JSON-schema для входных данных, обработка транспорта, настройка сессий. Каждая команда изобретала одну и ту же интеграцию заново.

Пакет https://github.com/yvv4git/go-juggler-mcp - это тот самый клей, написанный один раз и хорошо. Это MCP-сервер под лицензией MIT, который отдаёт весь интерфейс автоматизации Juggler - ARIA-снимки, стабильные ссылки на элементы, клики, ввод текста, выполнение JavaScript, анализ сети - как девятнадцать инструментов, которые может вызывать любой MCP-клиент. OpenCode, Claude Desktop, Cursor: все они говорят на одном протоколе, и этот сервер отвечает им тем же в сторону браузера Camoufox.

Сначала немного контекста: что такое MCP?

MCP (Model Context Protocol) - открытый протокол, представленный Anthropic в конце 2024 года, который стандартизирует взаимодействие ИИ-приложений с инструментами и источниками данных. Вместо того чтобы каждый агент встраивал собственный код вызова инструментов, сервер объявляет свои инструменты как JSON-схемы, а клиент вызывает их через хорошо определённый формат обмена:

запрос:
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "snapshot", "arguments": { "tab_id": "..." } } }

ответ:
{ "jsonrpc": "2.0", "id": 1, "result": { "content": [...] } }

Один сервер может использовать любой совместимый клиент, а один клиент - общаться со множеством серверов. Транспорты тоже подключаются: локальные серверы работают через stdio, удалённые - через streamable HTTP.

Экосистема MCP - это место, где автоматизация браузера становится по-настоящему практичной для агентов. Модели не нужен собственный плагин под каждый клиент - нужен один сервер, который отдаёт open_tab, snapshot, click, type как обычные инструменты. Именно это и предоставляет go-juggler-mcp.

Что такое go-juggler-mcp

go-juggler-mcp - это Go-бинарник, который располагается между MCP-клиентом и браузером с поддержкой Juggler. Цепочка выглядит так:

ИИ-клиент (opencode, Claude Desktop, Cursor)
        │  MCP (stdio или streamable HTTP)
        ▼
go-juggler-mcp
        │  REST (JSON поверх HTTP)
        ▼
camofox-browser
        │  протокол Juggler
        ▼
Camoufox / Firefox (с патчами stealth)

Внизу - Camoufox, антидетект-браузер, который подменяет hardwareConcurrency, WebGL-рендереры, AudioContext, геометрию экрана и WebRTC на уровне C++ - до того, как JavaScript вообще увидит страницу. Бразуер https://github.com/daijro/camofox оборачивает этот движок в REST API, созданный для агентов: accessibility-снимки, стабильные ссылки на элементы, изоляция сессий. Пакет https://github.com/yvv4git/go-juggler предоставляет Go-клиент для этого API. go-juggler-mcp добавляет верхний слой: он регистрирует каждый метод go-juggler как MCP-инструмент, и весь стек становится доступен из промпта.

Сборка из исходников (Go 1.26+):

go build -o go-juggler-mcp .

Быстрый старт

Единственное обязательное условие - запущенный экземпляр Camoufox, доступный через camofox-browser:

docker run -d -p 9377:9377 --name camoufox camoufox

Затем запустите сервер:

./go-juggler-mcp serve

С транспортом по умолчанию (stdio) сервер ждёт MCP-клиента на stdin/stdout. Пропишите его в конфиге opencode:

{
  "mcp": {
    "juggler": {
      "type": "local",
      "command": ["/path/to/go-juggler-mcp", "serve"]
    }
  }
}

И теперь модель может сама ходить по сайтам. Слово juggler в промпте говорит opencode, к какому MCP-серверу обращаться:

opencode run -m "opencode/deepseek-v4-flash-free" \
  "Open https://rutube.ru with juggler, snapshot the page, and summarize
   the main blocks, headings, navigation, and the first 10 clickable
   elements with their refs"

Один промпт - и агент открыл реальную вкладку, снял ARIA-снимок и рассуждает о живой странице: никаких селекторов, написанных вручную, никакого HTML в контексте.

Возможности

Сейчас go-juggler-mcp предоставляет девятнадцать инструментов - отображение один-в-один на REST-клиент go-juggler:

  • health - проверить статус браузера (движок, соединение, память)

  • open_tab - открыть новую вкладку и перейти по URL

  • navigate - загрузить URL в существующей вкладке

  • snapshot - получить ARIA-дерево страницы (ссылки на элементы)

  • click - кликнуть по элементу по ref или CSS-селектору

  • type - заполнить поле ввода по ref или селектору

  • press - нажать клавишу клавиатуры (Enter, Tab, Escape и т. д.)

  • scroll - прокрутить страницу вверх/вниз на N пикселей

  • back - перейти назад по истории

  • forward - перейти вперёд по истории

  • refresh - перезагрузить текущую страницу

  • links - список всех ссылок на странице с пагинацией

  • screenshot - сделать скриншот, вернуть или сохранить на диск

  • evaluate - выполнить произвольный JavaScript в контексте страницы

  • network_requests - получить все загруженные ресурсы (навигация + подресурсы)

  • stats - получить состояние вкладки (URL, посещённые URL, refs)

  • list_tabs - список всех вкладок в сессии

  • close_tab - закрыть вкладку

  • close_session - уничтожить всю сессию со всеми вкладками

Три из них заслуживают более пристального внимания.

Скриншоты, которые влезают в диалог

Инструмент screenshot - это место, где сервер добавляет реальную ценность, а не просто тупой HTTP-прокси. "Сырой" скриншот Camoufox - это PNG размером с вьюпорт; агенту с vision-моделью он нужен, а агенту без неё - компактный JPEG или вообще ничего.

По умолчанию инструмент возвращает изображение как base64 внутри результата MCP, которое vision-модель может прочитать напрямую:

Screenshot of tab 60bf9c8c-e6d9-4be0-ba09-738058215af6 (248732 bytes)

Передайте аргумент path - и сервер запишет файл на диск вместо этого: удобно, когда нужно сохранить артефакты или отдать их модели без vision. format (png/jpeg), quality (1-100, по умолчанию 85) и max_width (уменьшение) дают агенту контроль над размером ответа. Пайплайн изображений декодирует PNG, при необходимости уменьшает его масштабированием Catmull-Rom и перекодирует - всё в процессе, без внешних инструментов работы с картинками.

Сессии без конфигурации

Протокол Juggler группирует вкладки в сессии. Ручное управление ключами сессий - ровно та бухгалтерия, которой агент не должен заниматься. Если запустить go-juggler-mcp без --session, он сгенерирует уникальный ключ (mcp-<нано-время>) при старте, и каждый инструмент будет использовать его по умолчанию:

./go-juggler-mcp serve --addr http://localhost:9377 --session demo

Каждый инструмент также принимает необязательный аргумент session, так что один сервер может обслуживать несколько изолированных сессий от разных агентов - полезно, когда несколько MCP-клиентов делят один сервер.

Два транспорта в одном бинарнике

Локальным инструментам вроде opencode и Claude Desktop нужен stdio: сервер запускается как дочерний процесс и общается через stdin/stdout. Удалённым сценариям нужен streamable HTTP-транспорт, чтобы сервер мог работать на машине с браузером и быть доступным по сети:

./go-juggler-mcp serve --transport http --http-addr :8080

Тот же бинарник переключается между ними одним флагом - без пересборки и без отдельных пакетов. Удалённый режим прописывается в opencode как "type": "remote", указывающий на http://localhost:8080/mcp.

Статус и честный план развития

go-juggler-mcp пока молод - базовая поверхность инструментов появилась в первом же проходе - поэтому будем честны о том, что работает сегодня, а что нет.

Работает сегодня: все девятнадцать инструментов на обоих транспортах (stdio и streamable HTTP), генерация сессий без конфигурации, пайплайн скриншотов (возврат base64 или запись на диск, PNG/JPEG, качество и изменение размера), TOML-конфиг с переопределением флагами, корректное завершение по SIGINT/SIGTERM и набор мок-тестов обработчиков инструментов.

Ещё нет: MCP-ресурсов (сегодня сервер только про инструменты), шаблонов промптов и аутентификации на HTTP-транспорте - поэтому не стоит выставлять удалённый режим в недоверенную сеть. Список ресурсов, более богатые возможности сервера и аутентификация для HTTP-транспорта - естественные следующие шаги по мере развития проекта.

Для основной задачи - дать MCP-клиенту возможность управлять stealth-браузером Camoufox уже сегодня - go-juggler-mcp готов.

Итог

История "автоматизация браузера для агентов" долго была лоскутным одеялом из плагинов под каждый клиент и самописного клея. go-juggler-mcp стандартизирует всё это: один бинарник, один протокол и браузер со спуфингом отпечатков на уровне C++, вызываемый из любого MCP-клиента. Если вашим агентам нужны настоящие руки в настоящем вебе - это быстрый способ их дать.

Ссылки: