# MCP: Parreq в ИИ-агенте

> Один файл, который даёт агенту поиск, загрузку страниц и живой браузер

Источник: https://docs.parreq.com/mcp/

MCP (Model Context Protocol) — то, чем Claude Desktop, OpenClaw и другие агенты
подключают внешние инструменты. Мост Parreq — **один исполняемый файл**: скачали,
прописали в настройках агента, ключ в переменную окружения. Ни Python, ни Node,
ни прав администратора не нужно.

> **К сведению.**
>   Файл собран статически: на Linux он одинаково работает и на Alpine с musl, и на
>   Debian или Ubuntu с glibc. Разбираться, какая у вас libc, не придётся.

## Скачать

| Система | Файл |
|---|---|
| Windows | [parreq-mcp-windows-amd64.exe](https://parreq.com/dist/parreq-mcp-windows-amd64.exe) |
| Linux x86-64 | [parreq-mcp-linux-amd64](https://parreq.com/dist/parreq-mcp-linux-amd64) |
| Linux ARM64 | [parreq-mcp-linux-arm64](https://parreq.com/dist/parreq-mcp-linux-arm64) |
| macOS Apple Silicon | [parreq-mcp-darwin-arm64](https://parreq.com/dist/parreq-mcp-darwin-arm64) |

Рядом с каждым файлом лежит `.sha256` — проверить, что скачалось именно то:

```bash
curl -sSLO https://parreq.com/dist/parreq-mcp-linux-amd64
curl -sSLO https://parreq.com/dist/parreq-mcp-linux-amd64.sha256
sha256sum -c parreq-mcp-linux-amd64.sha256
chmod +x parreq-mcp-linux-amd64
```

## Настроить

Ключ выдаётся в [кабинете](https://parreq.com/lk/). Мост берёт его из окружения —
в самом файле никаких настроек нет.

```json Claude Desktop (Windows)
{
  "mcpServers": {
    "parreq": {
      "command": "C:\\Users\\Вы\\parreq-mcp-windows-amd64.exe",
      "env": { "PARREQ_API_KEY": "pr_ВАШКЛЮЧ" }
    }
  }
}
```

```json Claude Desktop (Linux, macOS)
{
  "mcpServers": {
    "parreq": {
      "command": "/home/вы/parreq-mcp-linux-amd64",
      "env": { "PARREQ_API_KEY": "pr_ВАШКЛЮЧ" }
    }
  }
}
```

Файл настроек Claude Desktop лежит здесь:

- Windows — `%APPDATA%\Claude\claude_desktop_config.json`
- macOS — `~/Library/Application Support/Claude/claude_desktop_config.json`

После правки агент нужно перезапустить.

### Переменные

| Переменная | По умолчанию | Зачем |
|---|---|---|
| `PARREQ_API_KEY` | — | ключ, обязательно |
| `PARREQ_API_URL` | `https://api.parreq.com` | другой адрес API |
| `PARREQ_TIMEOUT` | `180` | предел ожидания в секундах |

## Что получает агент

| Инструмент | Что делает |
|---|---|
| `parreq_search` | поиск в Google, разобранная выдача |
| `parreq_fetch` | страница по адресу глазами браузера |
| `parreq_crawl` | обход каталога: разделы, подразделы и карточки товаров |
| `parreq_browser_open` | открыть страницу в живой вкладке, получить список кнопок и полей |
| `parreq_browser_click` | нажать на элемент |
| `parreq_browser_fill` | заполнить одно поле |
| `parreq_browser_form` | заполнить анкету целиком и нажать кнопку отправки |
| `parreq_browser_state` | перечитать страницу, ничего на ней не делая |
| `parreq_browser_close` | закрыть сессию |

> **Примечание.**
>   Попросили `extract`, а `parsed` в ответе нет — причина лежит рядом, в
>   `extract_note`: из `fetch_metadata.extract_note` облака или из `note` и
>   `unsupported` коробки (в ней разбора моделью нет — страница не покидает
>   вашу машину; задайте поля селекторами через `fields`). Раньше ответ приходил
>   без `parsed` и без единого слова.

Описания составлены так, чтобы агент сам выбирал верный инструмент: в них
сказано не только что делает каждый, но и **чем он отличается от соседнего** —
иначе агент берёт `fetch` там, где нужен `search`, и открывает сессию ради одной
страницы.

## Как выглядит работа

Агент открывает страницу и получает элементы со ссылками `ref`:

```json
{
  "session_id": "bs_9f2a41c7e8b0",
  "elements": [
    {"ref": "pq1-k3f9x", "kind": "field", "text": "Почта", "type": "email"},
    {"ref": "pq2-m8p2q", "kind": "button", "text": "Войти"}
  ],
  "idle_left": 60,
  "life_left": 118
}
```

Дальше — заполняет поле и нажимает кнопку по этим `ref`, а в ответе видит, что
из этого вышло: сменился ли адрес, что теперь на странице.

> **Внимание.**
>   Идентификатор приходит в поле `session_id`, а в остальные инструменты кладётся
>   в поле **`session`**. Имена разные не по недосмотру: `session_id` — служебное
>   поле у части посредников, через которых агенты подключают MCP-серверы, и они
>   забирают его себе, не доводя до моста. Снаружи это выглядело как «параметр не
>   задан», хотя агент его послал. Старое имя мост по-прежнему принимает, если вы
>   зовёте его напрямую.

## Если страница пришла пустой

Так бывает, когда сайт отдаёт каркас, а содержимое приезжает сторонним виджетом:
`elements_count: 0`, а в `settled` стоит `ready: "loading"` и десяток-другой
узлов. Ждать дольше — `wait_ms` до 60 секунд, можно вместе с `wait_for` и
CSS-селектором того, что должно появиться:

```json
{"url": "https://пример", "include": "buttons,fields", "wait_ms": 40000}
```

Если сессия уже открыта, перечитать страницу дешевле, чем открывать заново, —
`parreq_browser_state` с тем же `session`.

## Размер ответа

Окно агента — общий и исчерпаемый ресурс: страница средней руки весит под двести
тысяч символов разметки, и одна такая выдача занимает весь разговор целиком.
Поэтому мост отдаёт агенту не всё, что пришло от сервиса, а ровно то, что тот
попросил, и не больше `max_chars` символов — по умолчанию 20 000.

| Параметр | По умолчанию | Что делает |
|---|---|---|
| `include` | текст (у сессий — `buttons,fields`) | что вернуть сверх этого: `html`, `js`, `css`, `network` — через запятую |
| `max_chars` | `20000` | предел ответа в символах, потолок — `120000` |

Выброшенное не исчезает молча: на его месте остаётся отметка с размером и
подсказкой, как его получить.

```json
{
  "text": "…",
  "html_omitted": {
    "chars": 119085,
    "hint": "поле \"html\" не запрошено; чтобы получить, добавьте include=\"html\""
  }
}
```

Обрезанное поле помечается так же — `text_truncated` с полным и показанным
размером, чтобы агент не принял обрубок за целую страницу. Резать по символам, а
не по байтам, здесь принципиально: обрезка русского текста посередине буквы
отдала бы битую строку, на которой споткнулся бы разбор ответа.

## Скриншот приходит картинкой

Попросите снимок — и агент увидит саму страницу, а не ссылку на неё. Мост
скачивает картинку и прикладывает её к ответу отдельным вложением: модель
получает и разобранный JSON, и изображение.

```json
{"name": "parreq_fetch", "arguments": {
  "url": "https://example.com", "include": "screenshot"}}
```

В ответе рядом с текстом появляется блок с картинкой, а в самом JSON —
отметка, что она приложена:

```json
{
  "final_url": "https://example.com/",
  "text": "Example Domain…",
  "screenshot_attached": true,
  "screenshot_bytes": 21804
}
```

Полезно там, где текст не отвечает на вопрос: «почему форма не отправилась»,
«что за баннер перекрыл страницу», «как выглядит вёрстка». По тексту это не
видно, по снимку видно сразу.

> **Примечание.**
>   Снимок — платная надстройка, как и в обычном Fetch. Картинка весом больше
>   шести мегабайт не прикладывается: она вытеснила бы из окна модели всё
>   остальное. Тогда в ответе остаётся ссылка и объяснение, почему вложения нет.

## Режим коробки

Если у вас стоит [коробка](https://docs.parreq.com/box), укажите мосту её адрес — и набор инструментов
поменяется. Вместо восьми штук с подробными схемами появится один: коробка
умеет разобрать команду сама, и агенту достаточно строки.

```json
{
  "mcpServers": {
    "parreq": {
      "command": "/usr/local/bin/parreq-mcp",
      "env": {
        "PARREQ_API_KEY": "pr_ваш_ключ",
        "PARREQ_API_URL": "http://127.0.0.1:8123"
      }
    }
  }
}
```

Режим включается сам, когда адрес на петле. Для коробки на соседней машине
задайте `PARREQ_BOX=1`.

| Команда | Кратко | Что делает |
|---|---|---|
| `search <запрос>` | `s` | выдача Google |
| `fetch <адрес>` | `f` | текст страницы |
| `parse <адрес> имя=селектор` | `p` | поля со страницы |
| `open <адрес>` | `o` | открыть вкладку |
| `click <вкладка> <ref>` | `c` | нажать элемент |
| `type <вкладка> <ref> <текст>` | `t` | заполнить одно поле |
| `form <вкладка> <ref>=<значение>; …` | `m` | заполнить анкету целиком |
| `read <вкладка>` | `r` | перечитать вкладку |
| `close <вкладка>` | `x` | закрыть вкладку |
| `shot <адрес или вкладка>` | `i` | снимок картинкой |
| `tabs` | | какие вкладки открыты |

Слова и буквы работают одинаково — пишите как удобнее. Ответы урезаны: текст до
шести тысяч знаков, элементы страницы короткими ссылками вида `b3`. Добавьте
`full` в конец команды, чтобы получить всё целиком.

```
open https://example.com
click 1 b3
type 1 i2 кофемашина
form 1 i3=Иван Петров; i5=+375290001100; i7=да; submit=b5
shot 1
close 1
```

Зачем это нужно: описания восьми инструментов агент отправляет модели при
каждом обращении, а это несколько тысяч токенов независимо от того, нужен ему
сейчас поиск или нет. Один инструмент со строкой занимает десятки.

## Отказы

Мост различает два вида неудач, и это важно для поведения агента.

**Ошибка протокола** — запрос неправильный: нет такого инструмента, не
разобрались аргументы. Повторять бессмысленно.

**Отказ инструмента** — приходит обычным ответом с признаком ошибки и полем
`retryable`:

```json
{ "ok": false, "error": "warming_up: обработчик готовится",
  "retryable": true, "retry_after_seconds": 120 }
```

`retryable: true` означает, что повтор имеет смысл — обработчик греется, лимит
временный, сессии заняты. `false` — повторять нечего: кончились кредиты, нет
прав, страница не открылась.

## Проверить, что работает

Мост запускается агентом, а не руками, но убедиться, что файл живой, можно так:

```bash
./parreq-mcp-linux-amd64 --version
```

А целиком — отправив ему запрос протокола:

```bash
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
  | PARREQ_API_KEY=pr_ВАШКЛЮЧ ./parreq-mcp-linux-amd64
```

В ответ придёт список из восьми инструментов.

## Обновления

Мост обновляется сам, начиная с версии 0.3.1. Устроено это иначе, чем у
коробки, и разница из-за срока жизни: мост запускается на сессию агента и
гаснет вместе с ней, десятки раз в день. Перезапускать себя ему не нужно и
нельзя — стандартные потоки держит агент.

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

Что при этом проверяется: контрольная сумма, размер, и что скачанное вправду
запускается и представляется обещанной версией. Не сошлось — обновление не
ставится, мост работает дальше как работал. О сделанном он пишет одну строку в
поток ошибок, который агент показывает в своём журнале:

```
parreq-mcp: поставлена версия 0.3.2 — начнёт работать со следующего запуска моста
```

Выключить:

```json
"env": { "PARREQ_MCP_NO_UPDATE": "1" }
```

> **Примечание.**
>   Выключатель нужен там, где мосту нельзя ходить наружу, и там, где его файлом
>   управляет пакетный менеджер: подменять чужой файл — грубость. Если мост лежит
>   в каталоге без права записи, он это увидит и не станет ничего делать.

Проверить свою версию: `parreq-mcp --version`. Что считает актуальным сервер:

```bash
curl https://api.parreq.com/v1/mcp/version
```

## Что внутри

Никаких сторонних библиотек: MCP поверх stdio — это JSON-RPC 2.0 через
стандартный ввод-вывод, и он целиком помещается в стандартную библиотеку языка.
Меньше вес, меньше поводов для обновлений и на одну сторону меньше, которой надо
доверять на вашей машине.

Ключ не пишется на диск и не попадает в сообщения об ошибках: он живёт только в
окружении процесса.
