ffmcp
Provides tools for controlling Firefox browser, managing tabs, pages, cookies, history, bookmarks, and executing arbitrary WebExtension API calls, enabling full browser automation.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
browserskill
Расширения для Firefox и Chrome + CLI + скилл для Claude Code и Codex, дающие агентам полный доступ к твоим настоящим браузерам. Никакого MCP-сервера: агент вызывает CLI как обычную команду, а как ей пользоваться — описано в скилле. Транспорт целиком локальный: stdio и Unix-сокет, ни одного HTTP-запроса и ни одного открытого порта.
Как устроено
┌─ Unix-сокет ~/.browserskill/firefox.sock ─▶ browserskill-host.js ─▶ расширение Firefox
агент ──скилл──▶ browserskill.js
└─ Unix-сокет ~/.browserskill/chrome.sock ──▶ browserskill-host.js ─▶ расширение ChromeУ каждого браузера свой native-хост и свой сокет (права 0600). Хост поднимается самим
браузером при старте расширения и работает как брокер: к нему подключаются вызовы CLI.
Поэтому несколько агентов одновременно работают с одним браузером, а внешне не открыт
ни один сетевой порт.
Один CLI обслуживает оба браузера — какой использовать, задаёт флаг -b chrome|firefox
или переменная BROWSERSKILL_BROWSER; без них берётся единственный запущенный.
Ответы больше ~700 КБ (скриншоты, дампы DOM) автоматически режутся на чанки и собираются обратно в хосте — ограничение native messaging на размер сообщения обходится прозрачно.
Related MCP server: ruyipage-mcp
Установка
Одной командой (macOS):
curl -fsSL https://raw.githubusercontent.com/ruslankolmakov/browserskill/main/get.sh | bashget.sh клонирует репозиторий в ~/.browserskill/app (другой путь — переменная
BROWSERSKILL_SRC), ставит node через Homebrew, если его нет, запускает install.sh,
открывает страницы расширений в найденных браузерах и кладёт путь к расширению в буфер
обмена — остаётся нажать «Загрузить распакованное». Повторный запуск обновляет установку.
Из клона вручную:
git clone git@github.com:ruslankolmakov/browserskill.git ~/Projects/browserskill
cd ~/Projects/browserskill
./install.shinstall.sh кладёт манифесты native-хоста в каталоги Firefox и всех найденных браузеров на
Chromium, создаёт лаунчеры с абсолютным путём к node (браузер из Finder не видит
/opt/homebrew/bin) и ставит скилл для обоих агентов:
Claude Code:
~/.claude/skills/browserskill(другой каталог —CLAUDE_SKILLS_DIR).Codex:
~/.codex/skills/browserskill(учитываетсяCODEX_HOME; другой каталог —CODEX_SKILLS_DIR).
Затем ставим расширения — нужно хотя бы одно.
Firefox:
about:debugging#/runtime/this-firefoxЗагрузить временное дополнение… → выбрать
extension/manifest.json
Временное дополнение живёт до перезапуска Firefox. Чтобы поставить навсегда, нужен Firefox Developer Edition / Nightly / ESR с
xpinstall.signatures.required = falseвabout:config— тогда собери.xpi(npm run build-xpi) и установи черезabout:addons→ Установить дополнение из файла. В обычном релизном Firefox неподписанные расширения навсегда поставить нельзя — это ограничение Mozilla.
Chrome:
chrome://extensions→ включить Режим разработчикаЗагрузить распакованное расширение → выбрать каталог
extension-chromeID должен получиться
mifolcjccjkcdfdoebmkgklimogoemng— он зашит полемkeyв манифесте, и именно его разрешает манифест native-хостаЖелательно: в карточке расширения включить Разрешить пользовательские скрипты
Последний пункт нужен для eval на сайтах со строгим CSP — подробности ниже.
Распакованное расширение переживает перезапуск Chrome, но требует включённого режима
разработчика.
Проверка обоих браузеров сразу:
./bin/browserskill.js doctor
./bin/browserskill.js browsersПодключение к агентам
Отдельной настройки нет: install.sh ставит общий skill/SKILL.md для Claude Code
и Codex, подставляя абсолютный путь к репозиторию. Скилл описывает, как звать CLI,
какие операции есть и на какие грабли не наступать.
В Codex скилл можно вызвать явно: $browserskill, либо выбрать через /skills.
Если новый скилл не появился, перезапусти Codex. Для уже установленного browserskill
достаточно повторно запустить ./install.sh.
Любому другому агенту достаточно уметь запускать команду:
node /путь/к/browserskill/bin/browserskill.js <команда>Выбор браузера
browserskill browsers # кто доступен
browserskill -b chrome tabs # разовый вызов в Chrome
BROWSERSKILL_BROWSER=chrome browserskill statusБез флага браузер выбирается сам: единственный запущенный, при двух живых — Firefox. Флаг всегда сильнее переменной окружения. Состояния «закреплённый браузер» между вызовами нет — в отличие от рабочего окна, которое живёт в расширении.
Команды и операции
Короткие подкоманды (browserskill без аргументов): doctor, browsers, status, windows,
use-window, new-window, tabs, open, snapshot, read, eval, api, call.
Всё остальное — через call <op> '<json>', это ~40 операций моста:
Группа | Операции |
Рабочее окно |
|
Вкладки |
|
Страница |
|
Отладка |
|
Профиль |
|
Всё остальное |
|
Полный справочник с примерами вызовов — в skill/SKILL.md.
api — это и есть «полный доступ». Он вызывает любой метод WebExtension API
напрямую, так что агент не ограничен готовым списком:
browserskill api tabs.query '[{"audible":true}]'
browserskill api browsingData.removeCache '[{}]'
browserskill api proxy.settings.set '[{"value":{"proxyType":"none"}}]'call browser.describe показывает, что вообще доступно ({"path": "cookies"} → список
методов). Наборы API у Firefox и Chrome разные, так что спрашивать стоит у того браузера,
в котором собираешься работать.
Рабочее окно
По умолчанию операции без явного tabId идут в активную вкладку текущего окна — то есть
туда, где сейчас работаешь ты. Чтобы агент не мешал, закрепи за ним окно:
browserskill new-window https://example.com # своё окно, сразу закреплено
browserskill use-window 3 # закрепить существующее
browserskill call session.useWindow '{}' # показать текущее закрепление
browserskill use-window release # снятьПосле закрепления в это окно уходят все операции без tabId, туда же открываются новые
вкладки, а tabs показывает только его вкладки (call tabs.list '{"allWindows":true}' — все).
В windows закреплённое окно помечено target: true, а в попапе расширения видно
строкой «Рабочее окно». Закрепление живёт отдельно в каждом браузере и снимается само,
если окно закрыть.
Работа со страницей
snapshot возвращает интерактивные элементы с короткими uid — это дешевле
скриншота и точнее селекторов:
{ "uid": "e12", "tag": "input", "type": "email", "text": "Email address", "rect": {...} }Далее call page.fill '{"uid":"e12","value":"..."}' и call page.click '{"uid":"e15"}'.
page.fill выставляет значение через нативный сеттер прототипа и шлёт input/change,
поэтому корректно работает с React, Vue и Svelte.
eval выполняет код в контексте страницы — это тело async-функции, доступны
await и return:
return [...document.querySelectorAll("h2")].map(h => h.innerText)Логи консоли и необработанные исключения собираются автоматически на каждой загруженной
странице (буфер на 2000 записей), сетевые запросы — через webRequest. Читать через
call logs.console и call logs.network. Вывод console.* из самого eval тоже
попадает в буфер.
Чем Chrome отличается от Firefox
Расширение для Chrome — Manifest V3, и часть вещей там устроена иначе. Набор операций одинаковый, отличается поведение:
Firefox | Chrome | |
Фон | постоянная фоновая страница | service worker, который браузер усыпляет |
Произвольный JS |
| мир страницы + |
Скриншот всей страницы | одним вызовом | прокрутка и сшивка кусков (медленнее, до 25 экранов) |
Скриншот неактивной вкладки | как есть | вкладку приходится на миг активировать |
Контейнеры |
| аналога нет, вызов честно падает |
Что из этого важно на практике:
evalи CSP. Код выполняется в мире страницы, а там действует её Content-Security-Policy. На сайтах со строгимscript-src(например GitHub)evalзапрещён. Обход — включить в карточке расширения «Разрешить пользовательские скрипты»: тогда browserskill выполнит код в отдельном мире, где CSP страницы не действует. Без этого на таких сайтах придёт понятная ошибка с этой же подсказкой. Операцииpage.click,page.fill,page.snapshotи остальные структурные операции CSP не касается вообще — они внедряются готовыми функциями, а не строками.Буферы логов и сон воркера. Service worker MV3 живёт от события до события. Расширение держит его будильником и переподключается автоматически, но если Chrome всё же усыпит воркер, накопленные
logs.consoleиlogs.networkобнулятся. Закрепление рабочего окна переживает это — оно лежит вstorage.session.Служебные страницы.
chrome://*, Chrome Web Store и PDF расширениям недоступны — там любая операция со страницей вернёт ошибку. В Firefox то же самое сabout:*иaddons.mozilla.org.
Примеры CLI
./bin/browserskill.js doctor # диагностика обоих браузеров
./bin/browserskill.js browsers # кто сейчас на связи
./bin/browserskill.js status # версия браузера, число вкладок
./bin/browserskill.js tabs # список вкладок
./bin/browserskill.js open https://example.com
./bin/browserskill.js snapshot 12 # элементы вкладки 12
./bin/browserskill.js eval 'return document.title'
./bin/browserskill.js api tabs.query '[{"pinned":true}]'
./bin/browserskill.js call page.text '{"tabId":12}'Браузер выбирается флагом --browser=chrome (или -b chrome), переменной
BROWSERSKILL_BROWSER, иначе автоматически:
./bin/browserskill.js -b chrome tabs
BROWSERSKILL_BROWSER=chrome ./bin/browserskill.js statusТесты
./tests/run.shЖивой браузер не нужен — браузеры и расширения заменяются заглушками. Проверяются: проход вызова CLI → сокет → хост → расширение, выбор браузера флагом, переменной и автоматически с маршрутизацией между двумя хостами, сборка чанкованных ответов, очистка сокета, отсутствие синхронных циклов при загрузке фона (отдельно для фоновой страницы Firefox и для service worker Chrome) и, отдельно, устойчивость обоих перехватчиков консоли к зацикливанию.
Последний тест не декоративный. В первой версии обмен со страницей шёл через
window.postMessage, а его видит и сама страница: если её код логирует полученные
сообщения (частый паттерн у виджетов и аналитики), возникала петля
console.log → postMessage → обработчик страницы → console.log. Каждая итерация уходила
в фон отдельным runtime.sendMessage, забивая главный поток родительского процесса
браузера, и он переставал реагировать на ввод. Сейчас обмен идёт приватным
CustomEvent, стоят защита от реентрантности, лимит 100 сообщений в секунду со страницы,
батчинг раз в 250 мс и общий потолок 500 записей в секунду в фоне.
Безопасность
Это по построению очень мощный доступ: агент видит твои cookies, историю и авторизованные сессии и может действовать от твоего имени на любом сайте.
Подтверждение подключения
Каждое новое подключение клиента к сокету пользователь подтверждает вручную. Пока
не подтверждено — все вызовы (кроме health-check ping и __status) висят, а хост
показывает нотификацию браузера. Клик по ней открывает popup расширения, где для запроса
предлагается выбор области:
это подключение — доступ только для текущего живого соединения; переподключился клиент — спросят снова;
на эту сессию — до перезапуска браузера (запоминается токен клиента в памяти хоста);
навсегда — токен клиента сохраняется в
~/.browserskill/allowed-<браузер>.json(0600) и переживает перезапуск.
Одобрение действует в пределах одного браузера: разрешив агенту Firefox, ты не разрешил ему заодно и Chrome — там он спросит отдельно.
Клиент идентифицируется стабильным токеном из ~/.browserskill/client-token (0600) — он
общий для всех вызовов CLI с этой машины, поэтому одобрение «навсегда» даётся один раз. Если
пользователь не реагирует за BROWSERSKILL_APPROVAL_TIMEOUT_MS (по умолчанию 120000 мс), доступ
отклоняется (fail-closed). Полностью выключить гейт — BROWSERSKILL_APPROVAL=0 (для headless/CI).
Ограничение платформы: кнопок в нотификациях Firefox нет, поэтому подтверждать нужно именно в popup (нотификация только сигналит и открывает его).
Сокеты лежат в
~/.browserskillс правами0600— доступны только твоему пользователю, никакой сети, ни локальной, ни внешней.Буферы
logs.consoleиlogs.networkпишутся постоянно, со всех вкладок, и в них оседает то, что страницы логируют сами. На практике это бывают почта, идентификаторы аккаунта, тариф и прочие персональные данные — например,claude.aiпечатает в консоль полный набор трейтов аналитики. Любой подключённый агент прочитает это одним вызовом. Чистить буфер:browserskill call logs.console '{"clear":true}'.Манифест хоста ограничивает подключение конкретным расширением:
allowed_extensionsсbrowserskill@localу Firefox,allowed_originsсchrome-extension://mifolcjccjkcdfdoebmkgklimogoemng/у Chrome.Чтобы временно всё отключить — выгрузи расширение (
about:debugging/chrome://extensions) или закрой браузер: сокет исчезает вместе с хостом.Логи хостов:
~/.browserskill/firefox.logи~/.browserskill/chrome.log.
Диагностика
Симптом | Причина |
| браузер не запущен либо расширение не загружено; |
| хост поднялся, но расширение отвалилось — жми «Переподключить» в попапе |
Значок расширения показывает | native-хост не запускается; смотри |
В Chrome ID расширения не | загружен каталог без поля |
| включи «Разрешить пользовательские скрипты» в карточке расширения Chrome |
| это внутренняя страница ( |
Вызовы висят, значок показывает | ждёт твоего подтверждения — открой popup browserskill и выбери область доступа |
| никто не нажал подтверждение за отведённое время; повтори вызов и подтверди в popup |
Агент переспрашивает доступ каждый раз | одобрено «на подключение»; выбери «на сессию» или «навсегда» |
В Chrome пропали логи консоли | service worker уснул и буферы обнулились — логи копятся заново с этого момента |
This server cannot be deployed
Maintenance
Related MCP Connectors
Official Browserless MCP server: browser automation, scraping, screenshots and PDFs for AI agents.
Live browser debugging for AI assistants — DOM, console, network via MCP.
Web scraping, browser automation, screenshots and AI data extraction for AI agents via MCP.
Remote MCP server exposing your Node Command fleet (files, shell, processes, browser) to AI hosts.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP server paired with a Firefox extension that enables LLM clients to control the user's browser, supporting tab management, history search, and content reading.17 npm339MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that exposes Firefox browser automation capabilities through the Model Context Protocol, enabling AI assistants to control web browsers for navigation, interaction, and data collection tasks.4BSD 3-Clause
- AlicenseAqualityDmaintenanceA MCP server that gives AI assistants full browser control, enabling navigation, clicking, form filling, and screenshots via any MCP client.8MIT
- AlicenseAqualityAmaintenanceA stealth Firefox browser exposed as an MCP server that lets AI agents browse and interact with real websites without being blocked by anti-bot systems.184MIT