Skip to main content
Glama
artdaal

express-mcp

by artdaal
README.md
# express-mcp

Неофициальный **MCP-сервер для мессенджера eXpress** и персональных агентов на macOS. Позволяет читать чаты и треды в группах, искать людей, отправлять сообщения и вложения, а также скачивать файлы с проверкой целостности. Авторизацией управляет постоянно работающий брокер сессии. Агенты подключаются к нему через локальный Unix socket и могут завершаться, не прерывая сессию.

**Начало работы:** [Установка](#установка-на-macos) → [Вход](#вход) → [Подключение к агентам](#подключение-к-агентам).

## Архитектура

![Архитектура брокера сессии и подключения агента по запросу](docs/diagrams/architecture.png)

- `sessiond` управляет взаимодействием с сервером и обновлением токенов. Системная блокировка не позволяет двум локальным брокерам одновременно владеть одной сессией.
- Токены, ключи, идентификатор устройства и номер поколения токенов хранятся вместе в отдельной записи macOS Keychain. Учётные данные официального приложения не читаются. Через MCP возвращаются содержимое чатов и диагностика без секретов.
- У каждого MCP-подключения свои короткоживущие подтверждения отправки и курсоры пагинации. При закрытии подключения они удаляются, но сессия брокера продолжает работать.
- Адреса серверов задаются явно и проверяются как HTTPS origins. При входе через QR адрес CTS должен точно совпасть с конфигурацией. HTTP-редиректы запрещены. Дополнительные корневые сертификаты можно подключить через `NODE_EXTRA_CA_CERTS` перед установкой.

![Последовательность входа через QR и обновления токенов](docs/diagrams/authentication.png)

## Установка на macOS

Нужны **Node.js 22+**, npm, активный вход пользователя в macOS с доступной связкой ключей `login` и Xcode Command Line Tools (`xcode-select --install`). Эта версия устанавливается из исходников и не опубликована в npm. Запуск брокера на Linux и Windows не поддерживается.

```sh
git clone https://github.com/artdaal/express-mcp.git
cd express-mcp
npm ci
npm run build
```

Создайте приватный JSON-файл конфигурации за пределами репозитория. У администратора вашей инсталляции нужно узнать **точный CTS origin**, адреса ETS и веб-клиента, а также идентификатор пакета клиента. Значения ниже приведены для примера — работающего сервиса по этим адресам нет:

```json
{
  "ctsOrigin": "https://cts.chat.example.com",
  "etsOrigin": "https://ets.chat.example.com",
  "webOrigin": "https://chat.example.com",
  "appVersion": "3.66.47",
  "packageId": "com.example.express",
  "clientProfile": "express-cli-web"
}
```

```sh
node dist/src/cli.js configure < /absolute/private/deployment.json
node dist/src/cli.js install
```

`configure` сохраняет конфигурацию в `~/Library/Application Support/express-mcp/` с доступом только для владельца. `install` компилирует небольшие утилиты на Swift, устанавливает пользовательский LaunchAgent и проверяет готовность брокера. Перед заменой LaunchAgent создаётся приватная резервная копия для отката. **Настройки агентских harness не меняются.** Повторяйте `install` после изменения конфигурации или обновления исходников. Не перемещайте каталог установленного репозитория.

## Вход

```sh
node dist/src/cli.js login
node dist/src/cli.js status
node dist/src/cli.js session-smoke
```

`login` открывает страницу с QR на том Mac, где работает брокер. Страница доступна только через loopback. Отсканируйте код официальным мобильным клиентом и подтвердите подключение устройства. В режиме совместимости на телефоне отображается **Chrome 149.0**, хотя браузерный движок для API-запросов не запускается. QR действует две минуты, а получить новый код на той же локальной странице можно в течение десяти минут.

`status` показывает локальное состояние. `session-smoke` проверяет авторизованный доступ: получает список чатов и читает одно недавнее сообщение, ничего не отправляя. Чтение может отметить чат прочитанным. Сам по себе `authState:ready` ещё не подтверждает работоспособность всей цепочки.

Подключайте **каждый Mac отдельно**. Не копируйте один ротируемый refresh token в два работающих брокера. При работе по SSH страница входа открывается на удалённом Mac. Для доступа к ней используйте доверенное удалённое подключение или локальный port forwarding; связка ключей пользователя на этом Mac должна быть доступна.

## Подключение к агентам

Указывайте абсолютные пути и запускайте MCP от того же пользователя macOS, что и брокер. В примерах замените `/absolute/express-mcp` на путь к своему репозиторию. После изменения настроек перезапустите или обновите MCP-сессию в harness.

### Codex

```sh
codex mcp add express -- /absolute/path/to/node /absolute/express-mcp/dist/src/cli.js serve
```

Эквивалентная запись в `~/.codex/config.toml`:

```toml
[mcp_servers.express]
command = "/absolute/path/to/node"
args = ["/absolute/express-mcp/dist/src/cli.js", "serve"]
```

Подробнее — в [документации по MCP в Codex](https://learn.chatgpt.com/docs/extend/mcp?surface=cli). Попросите агента вызвать `express_status`, затем получить список чатов или прочитать знакомый чат.

### Claude Code и другие MCP-клиенты

```sh
claude mcp add --transport stdio --scope user express -- /absolute/path/to/node /absolute/express-mcp/dist/src/cli.js serve
```

См. [настройку MCP в Claude Code](https://code.claude.com/docs/en/mcp). Для других harness подойдёт стандартная конфигурация stdio:

```json
{
  "mcpServers": {
    "express": {
      "command": "/absolute/path/to/node",
      "args": ["/absolute/express-mcp/dist/src/cli.js", "serve"]
    }
  }
}
```

### OpenClaw: подключение по запросу

Установите скилл в workspace нужного агента:

```sh
node scripts/install-skill.mjs --workspace /absolute/openclaw/workspace
```

Установщик копирует каталог скилла и сохраняет локальные пути к исполняемым файлам. **Глобальные MCP-инструменты не добавляются.** По умолчанию агент видит только короткое описание скилла; полные инструкции загружаются, когда он выбирает его для задачи. Начните новую сессию и попросите, например: «Найди в eXpress чат проекта и кратко перескажи последние ответы». Механизм описан в [документации OpenClaw](https://docs.openclaw.ai/tools/skills).

Скилл вызывает CLI с JSON-вводом и ограниченным объёмом результата. Подготовка и отправка выполняются в одном MCP-подключении: подтверждение не теряется между отдельными запусками клиента. Пример ручной проверки без отправки сообщений:

```sh
node dist/src/cli.js agent <<'JSON'
{"operation":"search-chats","query":"Проект","limit":50,"pages":3}
JSON
```

Проверьте, что OpenClaw обнаружил скилл: `openclaw skills --agent main info express-messenger --json`. Вместо `main` укажите ID своего агента. Если каталог уже установлен, но gateway всё ещё возвращает старый список скиллов, выполните `openclaw gateway restart` и начните новую сессию агента.

Все примеры запросов находятся в [инструкциях скилла](skills/express-messenger/SKILL.md). CLI не повторяет операции записи автоматически. `confirmed:true` означает, что вызывающая сторона подтверждает разрешение пользователя на конкретного получателя и содержимое; сам этот флаг не является отдельной системой контроля доступа. Перед обновлением скилла проверьте изменения и сохраните резервную копию: установщик не перезаписывает существующий каталог автоматически.

## Возможности и ограничения

| Назначение | MCP-инструменты с префиксом `express_` |
| --- | --- |
| Сессия и поиск | `status`, `list_chats`, `search_direct_chats`, `get_chat_info` |
| История переписки | `read_chat`, `list_threads`, `read_thread` |
| Текстовые сообщения | `prepare_message`, `send_message` |
| Вложения | `prepare_attachment`, `send_attachment`, `download_attachment` |

Для текста и вложений используются одноразовые подтверждения, привязанные к конкретному MCP-подключению и точному содержимому. Они действуют 120 секунд. На этапе подготовки вложения вычисляется хеш исходного файла; изменение файла делает подтверждение недействительным. Если результат загрузки или отправки неизвестен, автоматического повтора не будет. Изображение отправляется как зашифрованный PNG-оригинал с отдельно зашифрованным JPEG-превью. При скачивании проверяются подпись сообщения, целостность secretstream, размер и хеш расшифрованного файла. Результат сохраняется в новый приватный каталог.

Текущие ограничения: до 50 элементов на страницу MCP, до 20 страниц и примерно 200 KiB содержимого за один вызов CLI, до 10 MiB на вложение. Отправка в режиме изображения поддерживает только PNG. Список тредов ограничен недавними записями, глобального полнотекстового поиска нет. Некоторые старые сообщения могут не расшифровываться — для них возвращается явный признак ошибки. Интеграция неофициальная и зависит от версии протокола; настройки и политики разных инсталляций могут отличаться. Старый DOM-адаптер сохранён для регрессионных проверок, но для обычной установки рекомендуется брокер сессии.

## Обслуживание

```sh
npm test
npm run typecheck
launchctl kickstart -k "gui/$(id -u)/io.github.express-mcp.express-sessiond"
# Восстановить LaunchAgent из резервной копии, созданной командой install:
node scripts/install.mjs --restore /absolute/private/backup-directory
```

Если Keychain заблокирован, потребуется действие пользователя на Mac. Отзыв сессии или неопределённый результат refresh требуют нового QR; повторные попытки сами по себе проблему не устранят. Для диагностики ошибок сервера смотрите этап запроса и код ошибки в `status` — без секретов. При неопределённом результате отправки сначала проверьте историю целевого чата. Если файл загрузился, а сообщение не создалось, на сервере может остаться зашифрованный файл без сообщения; автоматическая очистка таких файлов пока не реализована.

## Разработка и источники

Тесты проверяют подписи QR-запросов, привязку к разрешённым origins, гонки и восстановление при refresh, изоляцию MCP-подключений, криптографию сообщений, шифрование и расшифровку файлов, ограничения CLI и установку пакета. Локальные материалы `.agent/`, учётные данные, браузерные профили, собранные бинарные файлы и тестовые данные не включаются в дистрибутив.

[eXpress CLI от IH8E](https://github.com/IH8E/express-cli/tree/2e58b5fbf4cc2e65c9e689fffa05bffc791ddd90) использовался как источник сведений о протоколе входа через QR в режиме совместимости с веб-клиентом. Он не является runtime-зависимостью, его исходный код здесь не распространяется. Тестовые примеры запросов содержат синтетические данные. Обработка refresh также учитывает консервативный подход из [RFC 9700 §4.14](https://www.rfc-editor.org/rfc/rfc9700.html#section-4.14).

Лицензия MIT. Проект не связан с разработчиком eXpress и не является официальным продуктом.