eXpress MCP connector
This server is a local MCP connector that lets an MCP client read and (optionally, with explicit approval) send text messages in the authenticated user's eXpress chats.
Check eXpress connection status without exposing credentials (
express_status).Search and list corporate or personal chats visible to the user (
express_list_chats), with optional query and include-left filters.Read and locally decrypt one page of chat history, up to 100 events per call, using
nextBeforeSyncIdfor older pages (express_get_history).Send a plain-text message to a specific chat after host confirmation, only when the server was started with
EXPRESS_ENABLE_SEND=1; requireschatId,text, and an idempotency UUID (express_send_message).Default operation is read-only; sending is opt-in and must be explicitly approved by the user.
Provides tools for interacting with the eXpress messenger: checking connection status, searching corporate and personal chats, reading message history, and sending text messages after explicit user confirmation.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@eXpress MCP connectorFind my eXpress chats named 'Support' and show the last 20 messages."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
eXpress MCP connector
Локальный MCP-сервер для работы с чатами пользователя eXpress. Коннектор регистрируется как отдельное устройство, получает только доступные пользователю чаты, локально расшифровывает историю и при отдельном разрешении может отправлять текстовые сообщения.
Возможности
проверка состояния подключения;
поиск корпоративных и личных чатов;
чтение доступной истории сообщений;
отправка простого текста после показа получателя и текста пользователю;
защита от повторной отправки при перезапуске или неопределённом ответе сервера;
удаление локальной сессии и ключей.
По умолчанию коннектор работает только на чтение. Сессия, токены и ключи хранятся в системном хранилище текущего пользователя: macOS Keychain, Windows Credential Manager или Linux Secret Service. Они не записываются в репозиторий и не возвращаются MCP-клиенту.
Related MCP server: WhatsApp MCP
Требования
Node.js 22 или новее;
мобильное приложение eXpress с уже выполненным входом;
разрешение организации на добавление пользовательского устройства;
Codex или другой MCP-клиент с поддержкой локальных STDIO-серверов.
Работа проверена на macOS. Реализация системного хранилища предусмотрена также для Windows и Linux, но её необходимо проверить в окружении конкретного пользователя.
Установка
git clone https://gitlab.mvs.group/ai/express-mcp-connector.git
cd express-mcp-connector
npm ci
npm run buildДля проверки локальной сборки:
npm testПодключение устройства eXpress
Запустите авторизацию из каталога проекта:
npm run auth:qrКоманда напечатает путь к временному PNG-файлу с QR-кодом. Откройте изображение, затем в мобильном eXpress перейдите в список открытых сессий, выберите добавление устройства и отсканируйте QR-код. Команда дождётся подтверждения и удалит временный файл после завершения.
Если организация использует другой публичный сервер eXpress:
npm run auth:qr -- --rts-host express.example.orgПри успешном завершении команда сообщит, подключён ли корпоративный профиль. Повторная авторизация после перезапуска компьютера не нужна, пока устройство или сессия не отозваны.
Подключение MCP
Сначала выполните npm run build. Локальный MCP-сервер запускается по STDIO
командой:
node /absolute/path/to/express-mcp-connector/dist/mcp/server.jsCodex на macOS или Linux
Находясь в каталоге проекта, добавьте сервер:
codex mcp add express -- "$(command -v node)" "$(pwd)/dist/mcp/server.js"Проверьте регистрацию:
codex mcp get expressПосле добавления перезапустите Codex, если он уже был открыт.
Codex на Windows PowerShell
$node = (Get-Command node).Source
$server = (Resolve-Path .\dist\mcp\server.js).Path
codex mcp add express -- $node $server
codex mcp get expressДля другого MCP-клиента создайте локальный STDIO-сервер с командой запуска
node и единственным аргументом — абсолютным путём к dist/mcp/server.js.
Проверка подключения
После запуска MCP попросите ассистента:
Проверь подключение к eXpress.
Затем можно проверить чтение:
Найди мои чаты eXpress с названием «Поддержка».
Покажи последние 20 сообщений из выбранного чата. Ничего не отправляй.
Корпоративные чаты используются по умолчанию. Для личного пространства явно
укажите ассистенту, что нужен personal scope.
Разрешение отправки сообщений
Отправка отключена при обычном подключении. Чтобы включить её, удалите текущую
запись MCP и добавьте сервер с переменной EXPRESS_ENABLE_SEND=1:
codex mcp remove express
codex mcp add express --env EXPRESS_ENABLE_SEND=1 -- \
"$(command -v node)" "$(pwd)/dist/mcp/server.js"На Windows используйте ранее полученные $node и $server:
codex mcp remove express
codex mcp add express --env EXPRESS_ENABLE_SEND=1 -- $node $serverДаже при включённой отправке MCP-клиент должен показать точный чат и полный текст и запросить подтверждение пользователя. Без подтверждения сообщение не отправляется.
Пример запроса:
Найди чат «Поддержка», подготовь сообщение «Проверка завершена» и покажи мне получателя и текст перед отправкой.
Доступные MCP-инструменты
express_status— проверяет готовность локальной сессии;express_list_chats— ищет и перечисляет доступные чаты;express_get_history— читает одну страницу истории, до 100 событий; для расшифрованных сообщений возвращаетsenderIdиз защищённого payload иsenderNameиз справочника eXpress. Если имя не найдено,senderNameравенnull— придумывать или угадывать имя по другим полям нельзя. Для пересылки полеforwardedFromотдельно содержит исходного автора и чат; при скрытой пересылке эти данные остаютсяnull;express_send_message— отправляет текст после явного подтверждения.
Для старых страниц истории клиент использует курсор nextBeforeSyncId,
возвращённый предыдущим запросом.
Восстановление и диагностика
Если QR-подключение завершилось, но корпоративный профиль ожидает повторного подтверждения:
npm run auth:cts-retryПроверить доступность корпоративного контура регистрации:
npm run auth:doctorЕсли администратор разрешил вход по корпоративной почте:
npm run auth:cts-email-start -- --email user@example.org
npm run auth:cts-email-confirmВторая команда запросит шестизначный код скрытым вводом. Код не сохраняется.
Если сессия сохранилась, но ключ отправки не зарегистрирован во всех доступных контурах:
npm run auth:repairЕсли результат отправки остался неопределённым, сначала проверьте историю чата. После проверки закройте запись одним из вариантов:
npm run send:reconcile -- <idempotency-uuid> delivered
npm run send:reconcile -- <idempotency-uuid> not_deliveredДля новой попытки после not_delivered используйте новый UUID и снова
подтвердите отправку.
Отключение
Удалите MCP из Codex:
codex mcp remove expressЗатем удалите локальную сессию, ключи и журнал отправок:
npm run auth:logoutПосле этого закройте устройство в списке открытых сессий eXpress, чтобы сервер также отозвал его токены.
Текущие ограничения
доступны только чаты и история, разрешённые подключённому пользователю;
глубина истории зависит от хранения на сервере, даты вступления в чат и доступных ключей;
поддерживаются чтение и отправка простого текста; вложения, реакции, редактирование, удаление, пересылка и управление участниками не реализованы;
за один вызов возвращается не более 100 событий;
коннектор использует пользовательские интерфейсы eXpress, совместимость которых может измениться после обновления сервера или клиента.
Available Tools
4 toolsexpress_get_historyRead eXpress chat historyARead-onlyIdempotent
Read and locally decrypt one backward page from a chat visible to the authenticated user. Use nextBeforeSyncId to request older pages.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| scope | No | corporate | |
| chatId | Yes | ||
| beforeSyncId | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint false, so the safety profile is covered. The description adds valuable behavioral context beyond annotations: local decryption, one backward page per call, and pagination via nextBeforeSyncId. There is no contradiction with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short, information-dense sentences with no filler. The primary action is front-loaded, and the pagination pointer is a necessary operational detail. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The annotations cover the read-only/idempotent safety profile, but the description omits essential parameter semantics (limit, scope, required chatId) and does not describe the return shape or page boundaries. For a 4-parameter tool with no output schema, an agent cannot reliably assemble correct calls beyond the defaults.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate by explaining parameters. It only hints at beforeSyncId's role ('request older pages'), while chatId, limit, and scope remain completely unexplained. An agent would not know what scope means, what limits to pass, or why chatId is required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Read'), a specific resource ('chat history page'), and a distinctive mode ('locally decrypt'). It also scopes to 'a chat visible to the authenticated user,' which clearly differentiates it from sibling tools like express_send_message (write) and express_list_chats (list).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for reading chat history, but it never explicitly contrasts it with siblings or states when not to use it. The only concrete usage guidance is pagination related ('Use nextBeforeSyncId to request older pages'), which helps after the first call rather than for initial tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
express_list_chatsList my eXpress chatsCRead-onlyIdempotent
List chats and direct conversations visible to the authenticated eXpress user.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | ||
| scope | No | corporate | |
| includeLeft | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, idempotent, non-destructive, and openWorld behavior, so the bar for extra disclosure is lower. The description adds the useful scope of 'visible to the authenticated eXpress user' but does not mention pagination, filtering behavior, or result shape. It does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no filler, front-loads the action and resource, and communicates the key authentication scope. It is appropriately concise for a simple list operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While annotations cover the safety profile, the description omits parameter semantics, output expectations, and any relationship to sibling tools. With no output schema and zero schema description coverage, this is insufficiently complete for reliable tool selection and invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description provides no explanation of the three parameters: query, scope, and includeLeft. Since neither the schema nor the description gives semantic meaning for these parameters, an agent cannot confidently construct a correct call.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List') and resource ('chats and direct conversations'), and adds the scoping detail that results are visible to the authenticated eXpress user. It is clear and distinguishable from the send/status siblings, though it does not explicitly differentiate itself from express_get_history.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this is for retrieving the current user's chats but gives no guidance about when to use express_list_chats versus express_get_history or other siblings. There are no explicit when-to-use, when-not-to-use, or alternative-selection conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
express_send_messageSend an eXpress messageADestructiveIdempotent
Encrypt and send a text message as the authenticated eXpress user. This external write is disabled unless the process owner sets EXPRESS_ENABLE_SEND=1 and must be approved by the MCP host.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| scope | No | corporate | |
| chatId | Yes | ||
| idempotencyKey | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a non-read-only, external, destructive, idempotent operation. The description adds meaningful context beyond those hints: the message is encrypted, the write is external, it is gated by an environment variable, and it requires MCP host approval. No contradiction with annotations is present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences: the first states the core action and identity, the second gives the critical operational caveat. There is no filler or repetition of schema information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Annotations cover safety and idempotency, and the description covers the unusual external-write gating and approval requirement. However, with no output schema and no parameter-level guidance in the description, the agent still lacks information about return behavior and the meaning of scope/idempotencyKey.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning. It only hints at the 'text' parameter by saying 'text message' and says nothing about chatId, scope, or idempotencyKey. The required idempotencyKey and the scope enum are left entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb and resource: 'Encrypt and send a text message as the authenticated eXpress user.' It unambiguously differentiates this from the sibling tools by saying this is a send operation, not listing, status, or history retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when the agent needs to send an eXpress message and gives important preconditions: the feature is disabled unless EXPRESS_ENABLE_SEND=1 and requires MCP host approval. However, it does not explicitly contrast this tool with siblings or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
express_statuseXpress connection statusARead-onlyIdempotent
Check whether the standalone eXpress user session is available without exposing credentials.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already cover read-only, idempotent, and non-destructive behavior. The description adds a useful security guarantee—'without exposing credentials'—which goes beyond the annotations and is especially relevant for a session-status tool. It does not describe the exact return format, but for a zero-input status check this is a minor gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, focused sentence that front-loads the action and includes the key credential-safety caveat without any filler. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple, parameterless status tool with rich read-only/idempotent annotations, the description provides enough information for an agent to select and invoke it correctly. The only omitted detail is the exact response shape, but 'check whether ... is available' sufficiently implies the outcome.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
This tool has zero parameters, and the schema is trivially complete with 100% coverage. There is nothing for the description to add about parameters, so the zero-parameter baseline of 4 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Check'), the resource ('standalone eXpress user session'), and the precise outcome ('is available'). It is clearly distinguishable from the sibling tools, which list chats, get history, or send messages.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the intended usage context clear: it is a session-availability check, likely a precondition for session-dependent operations. It does not explicitly name alternatives or state when not to use it, but no sibling tool is a plausible substitute for this status check.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.0- First observed
express_get_history - First observed
express_list_chats - First observed
express_send_message - First observed
express_status
TDQS
Scored across 4 tools
Each tool has a clearly separate purpose: listing conversations, checking session status, reading message history, and sending messages. There is no meaningful overlap between express_list_chats and express_get_history because one identifies chats and the other retrieves messages within a specific chat.
Tools consistently use the express_ prefix with a verb_noun structure, such as express_list_chats, express_get_history, and express_send_message. The only minor deviation is express_status, which uses a noun without an explicit verb like check.
Four tools is well-scoped for a chat connector focused on listing, reading, sending, and session status. Each tool serves a necessary function in the core workflow without unnecessary bloat.
The core chat workflow is covered: list chats, read paginated history, and send messages, plus a session status check. Missing advanced features like creating/deleting chats or managing messges are not essential for the apparent read-and-send scope.
Maintenance
Related MCP Connectors
Your own WhatsApp as an MCP server: read, search and send from any MCP client.
Send, search, and manage notifications, accounts, and push preferences
Explore your Messages SQLite database to browse tables and inspect schemas with ease. Run flexible…
Agent-to-agent messaging: directory, public lobby, DMs, channels, search. Stateless MCP + REST.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables reading, searching, and sending iMessages directly from MCP-compatible clients by accessing the local macOS iMessage database, supporting conversations, attachments, and both individual and group chats.584 npm10MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to list, read, search, and send WhatsApp messages via a persistent WebSocket connection with local SQLite storage.40 npmAGPL 3.0
- AlicenseBqualityBmaintenanceEnables reading, searching, sending iMessages, viewing image attachments, and managing conversations, with full support for modern macOS attributedBody parsing.141MIT
- AlicenseAqualityBmaintenanceEnables reading the local iMessage database and sending messages through Messages.app on macOS, with both local stdio and remote HTTP access.7MIT