Skip to main content
Glama
Vojtaupan

instantly-ai-mcp

by Vojtaupan

instantly-ai-mcp

MCP-сервер для v2 REST API сервиса Instantly.ai, который фиксирует то, что API делает на самом деле, а не доверяет тому, что говорят его документы. Каждая описанная ниже особенность была воспроизведена против живого API, а не скопирована из changelog или сообщения на форуме, и остаётся проверяемой: npm run verify-gotchas по требованию повторно проверяет живой аккаунт и помечает любое утверждение, чьё реальное поведение разошлось с описанным здесь (см. Почему эта таблица проверяется машиной — это ручная проверка, не часть CI).

Подводные камни

Эта таблица — причина, по которой репозиторий существует. Каждый сервер, построенный на этом API, рано или поздно открывает их для себя тяжёлым путём — обычно глядя на ошибку, которая выглядит как не то. Зафиксировано вживую 2026-08-21; о том, как таблица остаётся честной, см. Почему эта таблица проверяется машиной.

#

Утверждение

Вердикт

1

Cloudflare отклоняет User-Agent Python-urllib с 403 error code: 1010, что выглядит в точности как нехватка прав для API-ключа, но не является ею

HOLDS

2

DELETE отвергает любой запрос с телом или заголовком Content-Type (body must be null)

HOLDS

3

POST /leads/list молча игнорирует campaign_ids; рабочий фильтр — параметр в единственном числе campaign

HOLDS

4

GET /campaigns/analytics?id= молча игнорируется

REFUTED

5

Нефильтрованный GET /campaigns/analytics полностью пропускает черновые кампании

HOLDS

6

Поле часового пояса кампании — ограниченный enum: только America/Dawson, America/Chicago, America/Detroit

UNVERIFIABLE с помощью read-only-проверки

7

event_type вебхука уже, чем в документации: auto_reply_received и link_clicked описаны, но отклоняются с 400

UNVERIFIABLE с помощью read-only-проверки

8

Чтения внутренне несогласованы — /leads/list и /campaigns/analytics могут противоречить друг другу

UNVERIFIABLE (по своей природе перемежающийся)

Примечания к интересным строкам:

  • #3 — живая проверка отправила campaign_ids: [id] и получила 5 лидов, все 5 принадлежали другим кампаниям. Параметр не просто игнорируется — это молча неработающий фильтр; реально ограничивает запрос параметр в единственном числе campaign. list_leads именно поэтому проверяет собственное поле campaign каждого возвращённого лида и предупреждает, а не доверяет фильтру.

  • #4 — 2026-08-17 было зафиксировано HOLDS и перевернуто в REFUTED 2026-08-21. ?id= теперь корректно фильтрует аналитику до одной кампании. Ниже объясняется, почему именно этот переворот — весь смысл этого репозитория.

  • #5 — 2026-08-17 было UNVERIFIABLE (в аккаунте не было черновой кампании для проверки), затем подтверждено HOLDS живым интеграционным набором тестов (INSTANTLY_LIVE_TEST=1), который создаёт одноразовую черновую кампанию и подтверждает, что нефильтрованный /campaigns/analytics её пропускает. Приведённый выше HOLDS проверен именно так, а не read-only-проверкой verify-gotchas: эта проверка возвращает UNVERIFIABLE, когда в аккаунте ещё нет черновой кампании (она никогда не создаёт её), так что запуск против аккаунта без черновиков, как и ожидается, скажет «не удалось перепроверить», а не будет противоречить этой строке. list_campaigns именно поэтому читает из GET /campaigns — эта конечная точка черновики включает.

  • #6, #7, #8UNVERIFIABLE для read-only-проверки по принципу, а не случайно: #6 и #7 потребовали бы живой записи (создания кампании / вебхука), которую проверочный скрипт намеренно никогда не выполняет против реального аккаунта, а #8 — перемежающаяся проблема согласованности чтения, которую нельзя вызвать по требованию. UNVERIFIABLE — здесь настоящий, честный результат — см. ниже.

Почему эта таблица проверяется машиной

Таблица подводных камней, поддерживаемая вручную, гниёт. Утверждение #4 выше — тому доказательство: оно было записано как HOLDS 2026-08-17 и опровергнуто четыре дня спустя, 2026-08-21, когда Instantly, по-видимому, исправил параметр ?id= на стороне сервера. Четыре дня — это не долгий срок: именно так быстро недокументированный API может уйти от записанного на бумаге предположения.

npm run verify-gotchas повторно прогоняет проверку каждого утверждения против живого API и печатает таблицу из пяти колонок (#, Утверждение, Вердикт, Наблюдаемое, Последняя проверка) — надмножество трёхколоночной сводки выше, с сырыми данными живой проверки и датой её запуска. Это не та же форма, что у таблицы выше; не ждите побайтового совпадения.

Каждое утверждение также несёт документированный ожидаемый вердикт (HOLDS для #1–#3 и #5, REFUTED для #4, UNVERIFIABLE для #6–#8) — текущее задокументированное состояние, т.е. то, что этот README говорит сегодня. Скрипт завершается с ненулевым кодом только когда фактический вердикт проверки реально изменился относительно этого ожидания (например, документированный HOLDS вернулся как REFUTED), и печатает, какое именно утверждение отклонилось и в какую сторону. Повторное подтверждение уже документированного REFUTED (как #4) — не отклонение и не проваливает запуск; только новое изменение проваливает.

UNVERIFIABLE — реальный результат, о котором скрипт честно сообщает, а не сбой, который он замазывает, и он никогда не считается отклонением ни в какую сторону. Некоторые утверждения действительно нельзя проверить безопасной, read-only, неразрушающей проверкой (см. #6–#8 выше); скрипт так и говорит, а не угадывает и не пропускает молча. #5 — самый наглядный случай: его документированный HOLDS происходит из живого интеграционного набора тестов, а не из этой проверки, поэтому возврат проверки UNVERIFIABLE (черновой кампании сейчас нет) сообщается как «не удалось перепроверить» — не как сбой.

INSTANTLY_API_KEY=your-key npm run verify-gotchas

verify-gotchas запускается вручную, а не встроен в CI — посмотрите .github/workflows/ci.yml, там только build, typecheck и test. Это осознанный выбор, а не упущение: в CI нет живого API-ключа (скрипт чисто сам себя пропускает без него, печатая сообщение и выходя с 0 — см. начало scripts/verify-gotchas.ts — так что там он всё равно был бы молчаливым no-op), а этот скрипт существует, чтобы трогать конечные точки чтения реального аккаунта, чем CI репозитория не должен заниматься без присмотра. Запускайте его локально против своего аккаунта, когда хотите свежих данных.

Установка

{
  "mcpServers": {
    "instantly": {
      "command": "npx",
      "args": ["-y", "instantly-ai-mcp"],
      "env": { "INSTANTLY_API_KEY": "your-v2-api-key" }
    }
  }
}

Получите v2 API-ключ в панели Instantly в разделе Settings → Integrations → API. Требуется Node 20+.

Модель безопасности

Инструменты разбиты на три уровня, управляемые переменными окружения. Отключённый уровень вообще не регистрируется у MCP-сервера — модель, общающаяся с этим сервером, буквально не может увидеть или попытаться использовать инструмент, который ей не разрешён; это не проверка разрешений на этапе выполнения, которую можно обойти хитрым промптом.

Уровень

Включается

Инструменты

Поведение

Read (чтение)

всегда включён

6 инструментов

Только чтение. readOnlyHint: true.

Write (запись)

INSTANTLY_MCP_WRITE=1

5 инструментов

Создаёт/обновляет данные, но ничего необратимого.

Dangerous (опасный)

INSTANTLY_MCP_WRITE=1 и INSTANTLY_MCP_ALLOW_DANGEROUS=1

4 инструмента

Отправляет реальную почту, активирует кампании, удаляет данные.

Опасный уровень требует оба флага намеренно: включение обычных операций записи (загрузка лидов, блокировка адреса) никогда молча не включает заодно и активацию кампаний, отправку или удаление. Эти четыре инструмента дополнительно несут аннотацию MCP destructiveHint: true — подсказку, на которую совместимый клиент может отреагировать (например, запросив подтверждение у пользователя), даже когда уровень включён. Это поведение, навязываемое клиентом, а не гарантия со стороны этого сервера: клиент, игнорирующий подсказку, вызовет инструмент без какого-либо дополнительного шага подтверждения.

Инструменты

Чтение (всегда зарегистрированы)

  • list_campaigns — список всех кампаний, включая черновики, с расшифрованным числовым статусом.

  • list_accounts — список подключённых почтовых ящиков для отправки с оценкой прогрева, статусом и дневным лимитом.

  • campaign_state — сверка состояния одной кампании по трём независимым конечным точкам с сообщением о расхождениях, а не выбор «победителя». Чтение списка лидов ограничено страницей (одна страница, лимит 100); полная страница честно сообщается как ограниченная страницей, а не как расхождение Instantly.

  • list_leads — список лидов кампании, фильтруемый параметром в единственном числе campaign, с предупреждением, если собственное поле campaign какого-то из возвращённых лидов не согласуется. Читает одну страницу (лимит по умолчанию 100); pageLimited в результате сообщает, когда за её пределами могут существовать ещё лиды.

  • find_lead — поиск одного лида по email через параметр search; правильное второе мнение, когда list_leads выглядит неверным. search нечёткий, поэтому строка возвращается, только когда собственный адрес совпадает с запрошенным — почти-совпадение сообщается как null, никогда как лид.

  • list_replies — список полученных ответов с вырезанными цитируемой цепочкой/сигнатурой и расшифрованным статусом заинтересованности.

Запись (INSTANTLY_MCP_WRITE=1)

  • add_leads — загрузка лидов в кампанию, проверяемая по разности (не по счёту) через два независимых пути чтения. На кампанию с более чем 100 лидами проверочное чтение тоже ограничено страницей — об этом говорят поля pageLimited и note результата.

  • blocklist_address — блокировка одного полного адреса email; структурно отказывается от голых доменов.

  • update_lead — изменение полей лида.

  • create_campaign — создание кампании как черновика (никогда не отправляет); проверяет enum часовых поясов до любого сетевого вызова.

  • create_webhook — создание подписки вебхука; проверяет enum типов событий до любого сетевого вызова.

Опасные (INSTANTLY_MCP_WRITE=1 и INSTANTLY_MCP_ALLOW_DANGEROUS=1)

  • set_campaign_status — активация или приостановка кампании; активация немедленно начинает отправлять реальную почту.

  • send_reply — отправка реального, неотзываемого ответа лиду. Простой текст HTML-экранируется и разбивается на строки для тела html, а не вставляется сырым; передайте html сами, чтобы переопределить.

  • delete_lead — безвозвратное удаление лида.

  • delete_campaign — безвозвратное удаление кампании и её истории.

Известные ограничения

list_replies вырезает цитируемую исходную переписку и сигнатуру из каждого ответа (src/reply-text.ts). Он намеренно консервативен: при неоднозначном входе он оставляет цитату, а не рискует удалить реальный текст. Поэтому каждый оставшийся краевой случай ниже проваливается в БЕЗОПАСНУЮ сторону — цитируемая цепочка выживает в возвращаемом тексте, что является шумом, а не удаляется предложение, что было бы потерей данных:

  • Атрибуция, называющая только день недели, например On Tuesday ... wrote:, не несёт никакого сигнала даты/времени, который требуется вырезателю, поэтому не вырезается.

  • Атрибуция, называющая отправителя строчными буквами без адреса, например ... at 8:22 AM, john wrote:, не проходит проверку формы отправителя (настоящий отправитель — это адрес, имя с заглавной буквы или местоимение) и не вырезается.

  • Тело, целиком являющееся сигнатурой (-- на первой непустой строке, и ничего до неё), возвращается целиком, включая разделитель, а не опустошается.

Два излишне агрессивных случая обрезки, найденные при сборке, действительно удаляли реальный текст лида: тело, начинающееся с -- , было полностью вычищено, а текст вида On May 5: reasons you wrote: ... был ошибочно распознан как маркер цитируемого письма и вырезан. Оба исправлены до первого релиза и покрыты офлайн-набором тестов (test/reply-text.test.ts, "Fix round 4").

По-прежнему нет инструмента, который возвращает сырое, необрезанное body.text ответа. Если ответ из list_replies выглядит подозрительно коротким, проверьте его в панели Instantly, прежде чем делать вывод, что лид сказал меньше, чем сказал на самом деле.

Существующие аналоги

Уже есть пакет instantly-mcp от bcharleson — он покрывает похожую область и последний раз публиковался 2025-06-17. По состоянию на 2026-08-21 его npm-тег latest указывает на 1.0.5, а тег next содержит 3.0.5-1, — то есть обычный npx instantly-mcp устанавливает гораздо более старую сборку, чем самый новый опубликованный код самого пакета (dist-tags могут измениться после того, как это было написано; проверьте текущее состояние через npm view instantly-mcp dist-tags). Это факт, а не упрёк: instantly-ai-mcp — независимый, ничем не связанный проект с другой направленностью (таблица подводных камней и её самопроверка), а не форк и не замена.

Тестирование

Набор фикстур (npm test) работает полностью офлайн с моками клиентов и не требует API-ключа. Отдельный «живой» интеграционный набор, скрытый за INSTANTLY_LIVE_TEST=1 (и реальным INSTANTLY_API_KEY), обращается к настоящему API — но он только создаёт, читает и удаляет свою собственную одноразовую черновую кампанию (с именем zz-instantly-ai-mcp-throwaway-<timestamp>), никогда не затрагивает существующую кампанию или лид и никогда ничего не активирует и не отправляет. Он сам себя пропускает, когда флаг или ключ отсутствуют, — что в CI всегда так.

Лицензия

MIT

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Vojtaupan/instantly-ai-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server