Skip to main content
Glama
express-mcp

express-mcp

by artdaal

express-mcp

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

Начало работы: Установка → Вход → Подключение к агентам.

Архитектура

Архитектура брокера сессии и подключения агента по запросу

  • sessiond управляет взаимодействием с сервером и обновлением токенов. Системная блокировка не позволяет двум локальным брокерам одновременно владеть одной сессией.

  • Токены, ключи, идентификатор устройства и номер поколения токенов хранятся вместе в отдельной записи macOS Keychain. Учётные данные официального приложения не читаются. Через MCP возвращаются содержимое чатов и диагностика без секретов.

  • У каждого MCP-подключения свои короткоживущие подтверждения отправки и курсоры пагинации. При закрытии подключения они удаляются, но сессия брокера продолжает работать.

  • Адреса серверов задаются явно и проверяются как HTTPS origins. При входе через QR адрес CTS должен точно совпасть с конфигурацией. HTTP-редиректы запрещены. Дополнительные корневые сертификаты можно подключить через NODE_EXTRA_CA_CERTS перед установкой.

Последовательность входа через QR и обновления токенов

Related MCP server: imessage-kit-mcp

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

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

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

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

{
  "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"
}
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 после изменения конфигурации или обновления исходников. Не перемещайте каталог установленного репозитория.

Пример для achat.best

Для подключения к AChat с CTS cts1.achat.best используйте такую конфигурацию. Она не содержит токенов или ключей:

{
  "ctsOrigin": "https://cts1.achat.best",
  "etsOrigin": "https://ets.achat.best",
  "webOrigin": "https://achat.best",
  "appVersion": "3.66.47",
  "packageId": "com.pyligrim.alphach",
  "clientProfile": "express-cli-web"
}

Сохраните JSON вне репозитория, например в приватный achat.json, затем выполните:

node dist/src/cli.js configure < /absolute/private/achat.json
node dist/src/cli.js install
node dist/src/cli.js login
node dist/src/cli.js session-smoke

Отсканируйте QR официальным мобильным AChat и подтвердите устройство Chrome 149.0. Профиль express-cli-web задаёт совместимые заголовки и метаданные клиента; браузер для API-запросов не запускается.

ctsOrigin должен совпадать с CTS, который возвращается при QR-входе. Здесь https://achat.best — только адрес веб-клиента, его нельзя подставить вместо точного CTS для автоматического обнаружения. Если вашей учётной записи назначен другой CTS и возникает QR_CTS_ORIGIN_DENIED, уточните его точный HTTPS origin у администратора, измените конфигурацию и повторите configure, install, login. Проверка адреса и TLS остаётся обязательной.

Это отдельная установка express-mcp: она использует собственную запись Keychain, каталог ~/Library/Application Support/express-mcp/ и LaunchAgent io.github.express-mcp.express-sessiond. Ранее установленный achat-mcp с другой записью Keychain и LaunchAgent эти команды не обновляют. В MCP-клиенте запускайте dist/src/cli.js serve из нового checkout по примерам ниже; инструменты называются express_*.

Вход

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

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

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

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

Подробнее — в документации по MCP в Codex. Попросите агента вызвать express_status, затем получить список чатов или прочитать знакомый чат.

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

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

См. настройку MCP в Claude Code. Для других harness подойдёт стандартная конфигурация stdio:

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

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

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

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

Установщик копирует каталог скилла и сохраняет локальные пути к исполняемым файлам. Глобальные MCP-инструменты не добавляются. По умолчанию агент видит только короткое описание скилла; полные инструкции загружаются, когда он выбирает его для задачи. Начните новую сессию и попросите, например: «Найди в eXpress чат проекта и кратко перескажи последние ответы». Механизм описан в документации OpenClaw.

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

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 и начните новую сессию агента.

Все примеры запросов находятся в инструкциях скилла. 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-адаптер сохранён для регрессионных проверок, но для обычной установки рекомендуется брокер сессии.

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

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 и повторяет refresh только при доказанном сбое до передачи HTTP либо распознанном временном ответе сервера. Разблокируйте связку ключей login и восстановите сеть: перезапуск или новый QR для этих случаев обычно не нужны. Повторы выполняются одним writer с растущей задержкой до 5 минут; nextRetryAt показывает время следующей разрешённой попытки. Проверка таймера выполняется каждые 5 секунд и учитывает скачок часов после сна Mac.

Если сервер уже вернул новую пару токенов, а сохранение не подтверждено, брокер приватно удерживает эту точную пару в памяти и повторяет только сохранение. Пока оно не подтверждено, учётные данные недоступны: authState: locked, lastAuthErrorCode: REFRESH_SAVE_FAILED. Повторного HTTP-обмена в этой фазе нет. Ошибка сохранения перед первым обменом также восстанавливается в том же процессе, даже если Keychain успел записать fence перед ошибкой. После аварии это знание и несохранённая пара теряются: оставшийся на диске refreshPending требует нового QR и запрещает повтор старого refresh token.

Если сохранение нового входа завершилось ошибкой, брокер сначала сверяет точный результат с Keychain: запись могла уже состояться. До завершения сверки прежняя сессия и её несохранённая замена не обновляются. При штатном закрытии уже начатый HTTP-обмен завершается попыткой сохранения известной новой пары; ошибка этой попытки оставляет crash fence. Успешное отложенное сохранение сохраняет время получения пары в lastAuthenticatedRequestAt, а не отмечается как новый обмен с сервером.

Код или состояние в status

Действие

ENOTFOUND, EAI_AGAIN, ECONNREFUSED, ENETUNREACH, EHOSTUNREACH, UND_ERR_CONNECT_TIMEOUT, REFRESH_CONNECT_TIMEOUT, REFRESH_CONNECT_FAILED

Доказанный сбой до HTTP; восстановите сеть и дождитесь автоматического повтора. ENETUNREACH и EHOSTUNREACH разрешают повтор только при подтверждённом этапе connect.

KEYCHAIN_UNAVAILABLE, REFRESH_SAVE_FAILED, AUTH_SAVE_FAILED

Проверьте доступность Keychain и authState; при locked брокер повторяет безопасное восстановление или точное сохранение. reauth_required остаётся терминальным, даже если не удалось сохранить отзыв.

AUTH_STORE_INVALID

Сохранённые данные не соответствуют схеме; автоматический повтор загрузки не исправит их. Требуется новый QR.

KEYCLOAK_REFRESH_ERROR, RATE_LIMITED, retry_wait

Временный распознанный ответ; дождитесь nextRetryAt.

REFRESH_RESPONSE_LOST, REFRESH_RESPONSE_INVALID, REFRESH_OUTCOME_UNKNOWN, recovery_required

Результат обмена неизвестен; старый rotating token не повторяется. Требуется новый QR. Общий timeout, abort, reset и неизвестная ошибка относятся сюда.

OPENID_SESSION_NOT_FOUND, OPENID_OFFLINE_SESSION_INVALID, REFRESH_TOKEN_ERROR, REFRESH_TOKEN_NOT_FOUND, reauth_required

Сервер отверг сессию; требуется новый QR и, при регулярном повторении, проверка серверной политики.

authRecoveryHistory содержит последние 32 события текущего процесса в хронологическом порядке: только timestamp, phase, state, generation, code, outcome. Коды контролируются брокером; токены, ключи, идентификаторы аккаунта/устройства, адреса и исходные ошибки в историю не попадают. История возвращается копиями, не записывается в Keychain и исчезает после остановки процесса. Для диагностики сопоставляйте её с этапом и кодом ошибки в lastUpstreamError.

Автоматическое восстановление не продлевает жёсткие сроки жизни activation или OpenID/offline-сессии. При регулярном завершении авторизации передайте администратору безопасные коды, время и этап сбоя для проверки activation limits и сроков OpenID; эта локальная доработка не устанавливает причину ежедневного истечения и не меняет серверную политику. activation_limit_exceeded при входе тоже требует проверки лимитов, а не бесконечных QR-попыток.

Изменение исходного checkout само по себе не обновляет уже работающий брокер из другой установки. Проверяйте установленную версию и путь запуска перед отдельным обновлением. Локальные тесты ниже подтверждают поведение исходного кода; многодневная проверка работающей установки остаётся отдельной работой: сон/пробуждение, потеря сети, блокировка/разблокировка Keychain, перезапуск и успешное аутентифицированное чтение после восстановления. Такая проверка здесь ещё не пройдена.

При неопределённом результате отправки сначала проверьте историю целевого чата. Если файл загрузился, а сообщение не создалось, на сервере может остаться зашифрованный файл без сообщения; автоматическая очистка таких файлов пока не реализована.

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

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

eXpress CLI от IH8E использовался как источник сведений о протоколе входа через QR в режиме совместимости с веб-клиентом. Он не является runtime-зависимостью, его исходный код здесь не распространяется. Тестовые примеры запросов содержат синтетические данные. Обработка refresh также учитывает консервативный подход из RFC 9700 §4.14.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables reading and sending iMessages on macOS through MCP, with tools for managing chats, messages, and attachments via AI agents.
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables reading, sending, and managing iMessage conversations on macOS through MCP.
      1
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to send and receive iMessages and emails, and manage agent identities, in MCP-compatible clients.
      6
      20 npm
      MIT